mshtml: Call attached event handlers in reversed order.
[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 #include "mshtmdid.h"
28
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
31
32 #include "mshtml_private.h"
33 #include "htmlevent.h"
34 #include "resource.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 static struct list window_list = LIST_INIT(window_list);
39
40 static void window_set_docnode(HTMLWindow *window, HTMLDocumentNode *doc_node)
41 {
42     if(window->doc) {
43         abort_document_bindings(window->doc);
44         window->doc->basedoc.window = NULL;
45         htmldoc_release(&window->doc->basedoc);
46     }
47     window->doc = doc_node;
48     if(doc_node)
49         htmldoc_addref(&doc_node->basedoc);
50
51     if(window->doc_obj && window->doc_obj->basedoc.window == window) {
52         if(window->doc_obj->basedoc.doc_node)
53             htmldoc_release(&window->doc_obj->basedoc.doc_node->basedoc);
54         window->doc_obj->basedoc.doc_node = doc_node;
55         if(doc_node)
56             htmldoc_addref(&doc_node->basedoc);
57     }
58 }
59
60 nsIDOMWindow *get_nsdoc_window(nsIDOMDocument *nsdoc)
61 {
62     nsIDOMDocumentView *nsdocview;
63     nsIDOMAbstractView *nsview;
64     nsIDOMWindow *nswindow;
65     nsresult nsres;
66
67     nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentView, (void**)&nsdocview);
68     nsIDOMDocument_Release(nsdoc);
69     if(NS_FAILED(nsres)) {
70         ERR("Could not get nsIDOMDocumentView iface: %08x\n", nsres);
71         return NULL;
72     }
73
74     nsres = nsIDOMDocumentView_GetDefaultView(nsdocview, &nsview);
75     nsIDOMDocumentView_Release(nsview);
76     if(NS_FAILED(nsres)) {
77         ERR("GetDefaultView failed: %08x\n", nsres);
78         return NULL;
79     }
80
81     nsres = nsIDOMAbstractView_QueryInterface(nsview, &IID_nsIDOMWindow, (void**)&nswindow);
82     nsIDOMAbstractView_Release(nsview);
83     if(NS_FAILED(nsres)) {
84         ERR("Coult not get nsIDOMWindow iface: %08x\n", nsres);
85         return NULL;
86     }
87
88     return nswindow;
89 }
90
91 static void release_children(HTMLWindow *This)
92 {
93     HTMLWindow *child;
94
95     while(!list_empty(&This->children)) {
96         child = LIST_ENTRY(list_tail(&This->children), HTMLWindow, sibling_entry);
97
98         list_remove(&child->sibling_entry);
99         child->parent = NULL;
100         IHTMLWindow2_Release(HTMLWINDOW2(child));
101     }
102 }
103
104 static HRESULT get_location(HTMLWindow *This, HTMLLocation **ret)
105 {
106     if(This->location) {
107         IHTMLLocation_AddRef(HTMLLOCATION(This->location));
108     }else {
109         HRESULT hres;
110
111         hres = HTMLLocation_Create(This, &This->location);
112         if(FAILED(hres))
113             return hres;
114     }
115
116     *ret = This->location;
117     return S_OK;
118 }
119
120 static inline HRESULT set_window_event(HTMLWindow *window, eventid_t eid, VARIANT *var)
121 {
122     if(!window->doc) {
123         FIXME("No document\n");
124         return E_FAIL;
125     }
126
127     return set_event_handler(&window->doc->body_event_target, window->doc, eid, var);
128 }
129
130 static inline HRESULT get_window_event(HTMLWindow *window, eventid_t eid, VARIANT *var)
131 {
132     if(!window->doc) {
133         FIXME("No document\n");
134         return E_FAIL;
135     }
136
137     return get_event_handler(&window->doc->body_event_target, eid, var);
138 }
139
140 #define HTMLWINDOW2_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow2, iface)
141
142 static HRESULT WINAPI HTMLWindow2_QueryInterface(IHTMLWindow2 *iface, REFIID riid, void **ppv)
143 {
144     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
145
146     *ppv = NULL;
147
148     if(IsEqualGUID(&IID_IUnknown, riid)) {
149         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
150         *ppv = HTMLWINDOW2(This);
151     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
152         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
153         *ppv = HTMLWINDOW2(This);
154     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
155         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
156         *ppv = DISPATCHEX(This);
157     }else if(IsEqualGUID(&IID_IHTMLFramesCollection2, riid)) {
158         TRACE("(%p)->(IID_IHTMLFramesCollection2 %p)\n", This, ppv);
159         *ppv = HTMLWINDOW2(This);
160     }else if(IsEqualGUID(&IID_IHTMLWindow2, riid)) {
161         TRACE("(%p)->(IID_IHTMLWindow2 %p)\n", This, ppv);
162         *ppv = HTMLWINDOW2(This);
163     }else if(IsEqualGUID(&IID_IHTMLWindow3, riid)) {
164         TRACE("(%p)->(IID_IHTMLWindow3 %p)\n", This, ppv);
165         *ppv = HTMLWINDOW3(This);
166     }else if(IsEqualGUID(&IID_IHTMLWindow4, riid)) {
167         TRACE("(%p)->(IID_IHTMLWindow4 %p)\n", This, ppv);
168         *ppv = HTMLWINDOW4(This);
169     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
170         return *ppv ? S_OK : E_NOINTERFACE;
171     }
172
173     if(*ppv) {
174         IUnknown_AddRef((IUnknown*)*ppv);
175         return S_OK;
176     }
177
178     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
179     return E_NOINTERFACE;
180 }
181
182 static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface)
183 {
184     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
185     LONG ref = InterlockedIncrement(&This->ref);
186
187     TRACE("(%p) ref=%d\n", This, ref);
188
189     return ref;
190 }
191
192 static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface)
193 {
194     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
195     LONG ref = InterlockedDecrement(&This->ref);
196
197     TRACE("(%p) ref=%d\n", This, ref);
198
199     if(!ref) {
200         DWORD i;
201
202         remove_target_tasks(This->task_magic);
203         set_window_bscallback(This, NULL);
204         set_current_mon(This, NULL);
205         window_set_docnode(This, NULL);
206         release_children(This);
207
208         if(This->frame_element)
209             This->frame_element->content_window = NULL;
210
211         if(This->option_factory) {
212             This->option_factory->window = NULL;
213             IHTMLOptionElementFactory_Release(HTMLOPTFACTORY(This->option_factory));
214         }
215
216         if(This->image_factory) {
217             This->image_factory->window = NULL;
218             IHTMLImageElementFactory_Release(HTMLIMGFACTORY(This->image_factory));
219         }
220
221         if(This->location) {
222             This->location->window = NULL;
223             IHTMLLocation_Release(HTMLLOCATION(This->location));
224         }
225
226         if(This->screen)
227             IHTMLScreen_Release(This->screen);
228
229         for(i=0; i < This->global_prop_cnt; i++)
230             heap_free(This->global_props[i].name);
231
232         This->window_ref->window = NULL;
233         windowref_release(This->window_ref);
234
235         heap_free(This->global_props);
236         release_script_hosts(This);
237
238         if(This->nswindow)
239             nsIDOMWindow_Release(This->nswindow);
240
241         list_remove(&This->entry);
242         release_dispex(&This->dispex);
243         heap_free(This);
244     }
245
246     return ref;
247 }
248
249 static HRESULT WINAPI HTMLWindow2_GetTypeInfoCount(IHTMLWindow2 *iface, UINT *pctinfo)
250 {
251     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
252
253     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
254 }
255
256 static HRESULT WINAPI HTMLWindow2_GetTypeInfo(IHTMLWindow2 *iface, UINT iTInfo,
257                                               LCID lcid, ITypeInfo **ppTInfo)
258 {
259     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
260
261     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
262 }
263
264 static HRESULT WINAPI HTMLWindow2_GetIDsOfNames(IHTMLWindow2 *iface, REFIID riid,
265                                                 LPOLESTR *rgszNames, UINT cNames,
266                                                 LCID lcid, DISPID *rgDispId)
267 {
268     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
269
270     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
271 }
272
273 static HRESULT WINAPI HTMLWindow2_Invoke(IHTMLWindow2 *iface, DISPID dispIdMember,
274                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
275                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
276 {
277     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
278
279     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
280             pVarResult, pExcepInfo, puArgErr);
281 }
282
283 static HRESULT get_frame_by_index(nsIDOMWindowCollection *nsFrames, PRUint32 index, HTMLWindow **ret)
284 {
285     PRUint32 length;
286     nsIDOMWindow *nsWindow;
287     nsresult nsres;
288
289     nsres = nsIDOMWindowCollection_GetLength(nsFrames, &length);
290     if(NS_FAILED(nsres)) {
291         FIXME("nsIDOMWindowCollection_GetLength failed: 0x%08x\n", nsres);
292         return E_FAIL;
293     }
294
295     if(index >= length)
296         return DISP_E_MEMBERNOTFOUND;
297
298     nsres = nsIDOMWindowCollection_Item(nsFrames, index, &nsWindow);
299     if(NS_FAILED(nsres)) {
300         FIXME("nsIDOMWindowCollection_Item failed: 0x%08x\n", nsres);
301         return E_FAIL;
302     }
303
304     *ret = nswindow_to_window(nsWindow);
305
306     nsIDOMWindow_Release(nsWindow);
307
308     return S_OK;
309 }
310
311 static HRESULT WINAPI HTMLWindow2_item(IHTMLWindow2 *iface, VARIANT *pvarIndex, VARIANT *pvarResult)
312 {
313     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
314     nsIDOMWindowCollection *nsFrames;
315     HTMLWindow *window;
316     HRESULT hres;
317     nsresult nsres;
318
319     TRACE("(%p)->(%p %p)\n", This, pvarIndex, pvarResult);
320
321     nsres = nsIDOMWindow_GetFrames(This->nswindow, &nsFrames);
322     if(NS_FAILED(nsres)) {
323         FIXME("nsIDOMWindow_GetFrames failed: 0x%08x\n", nsres);
324         return E_FAIL;
325     }
326
327     if(V_VT(pvarIndex) == VT_I4) {
328         int index = V_I4(pvarIndex);
329         TRACE("Getting index %d\n", index);
330         if(index < 0) {
331             hres = DISP_E_MEMBERNOTFOUND;
332             goto cleanup;
333         }
334         hres = get_frame_by_index(nsFrames, index, &window);
335         if(FAILED(hres))
336             goto cleanup;
337     }else if(V_VT(pvarIndex) == VT_UINT) {
338         unsigned int index = V_UINT(pvarIndex);
339         TRACE("Getting index %u\n", index);
340         hres = get_frame_by_index(nsFrames, index, &window);
341         if(FAILED(hres))
342             goto cleanup;
343     }else if(V_VT(pvarIndex) == VT_BSTR) {
344         BSTR str = V_BSTR(pvarIndex);
345         PRUint32 length, i;
346
347         TRACE("Getting name %s\n", wine_dbgstr_w(str));
348
349         nsres = nsIDOMWindowCollection_GetLength(nsFrames, &length);
350
351         window = NULL;
352         for(i = 0; i < length && !window; ++i) {
353             HTMLWindow *cur_window;
354             nsIDOMWindow *nsWindow;
355             BSTR id;
356
357             nsres = nsIDOMWindowCollection_Item(nsFrames, i, &nsWindow);
358             if(NS_FAILED(nsres)) {
359                 FIXME("nsIDOMWindowCollection_Item failed: 0x%08x\n", nsres);
360                 hres = E_FAIL;
361                 goto cleanup;
362             }
363
364             cur_window = nswindow_to_window(nsWindow);
365
366             nsIDOMWindow_Release(nsWindow);
367
368             hres = IHTMLElement_get_id(HTMLELEM(&cur_window->frame_element->element), &id);
369             if(FAILED(hres)) {
370                 FIXME("IHTMLElement_get_id failed: 0x%08x\n", hres);
371                 goto cleanup;
372             }
373
374             if(!strcmpW(id, str))
375                 window = cur_window;
376
377             SysFreeString(id);
378         }
379
380         if(!window) {
381             hres = DISP_E_MEMBERNOTFOUND;
382             goto cleanup;
383         }
384     }else {
385         hres = E_INVALIDARG;
386         goto cleanup;
387     }
388
389     IHTMLWindow2_AddRef(HTMLWINDOW2(window));
390     V_VT(pvarResult) = VT_DISPATCH;
391     V_DISPATCH(pvarResult) = (IDispatch*)window;
392
393     hres = S_OK;
394
395 cleanup:
396     nsIDOMWindowCollection_Release(nsFrames);
397
398     return hres;
399 }
400
401 static HRESULT WINAPI HTMLWindow2_get_length(IHTMLWindow2 *iface, LONG *p)
402 {
403     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
404     nsIDOMWindowCollection *nscollection;
405     PRUint32 length;
406     nsresult nsres;
407
408     TRACE("(%p)->(%p)\n", This, p);
409
410     nsres = nsIDOMWindow_GetFrames(This->nswindow, &nscollection);
411     if(NS_FAILED(nsres)) {
412         ERR("GetFrames failed: %08x\n", nsres);
413         return E_FAIL;
414     }
415
416     nsres = nsIDOMWindowCollection_GetLength(nscollection, &length);
417     nsIDOMWindowCollection_Release(nscollection);
418     if(NS_FAILED(nsres)) {
419         ERR("GetLength failed: %08x\n", nsres);
420         return E_FAIL;
421     }
422
423     *p = length;
424     return S_OK;
425 }
426
427 static HRESULT WINAPI HTMLWindow2_get_frames(IHTMLWindow2 *iface, IHTMLFramesCollection2 **p)
428 {
429     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
430     FIXME("(%p)->(%p): semi-stub\n", This, p);
431
432     /* FIXME: Should return a separate Window object */
433     *p = (IHTMLFramesCollection2*)HTMLWINDOW2(This);
434     HTMLWindow2_AddRef(iface);
435     return S_OK;
436 }
437
438 static HRESULT WINAPI HTMLWindow2_put_defaultStatus(IHTMLWindow2 *iface, BSTR v)
439 {
440     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
441     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
442     return E_NOTIMPL;
443 }
444
445 static HRESULT WINAPI HTMLWindow2_get_defaultStatus(IHTMLWindow2 *iface, BSTR *p)
446 {
447     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
448     FIXME("(%p)->(%p)\n", This, p);
449     return E_NOTIMPL;
450 }
451
452 static HRESULT WINAPI HTMLWindow2_put_status(IHTMLWindow2 *iface, BSTR v)
453 {
454     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
455     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
456     return E_NOTIMPL;
457 }
458
459 static HRESULT WINAPI HTMLWindow2_get_status(IHTMLWindow2 *iface, BSTR *p)
460 {
461     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
462     FIXME("(%p)->(%p)\n", This, p);
463     return E_NOTIMPL;
464 }
465
466 static HRESULT WINAPI HTMLWindow2_setTimeout(IHTMLWindow2 *iface, BSTR expression,
467         LONG msec, VARIANT *language, LONG *timerID)
468 {
469     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
470     VARIANT expr_var;
471
472     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(expression), msec, language, timerID);
473
474     V_VT(&expr_var) = VT_BSTR;
475     V_BSTR(&expr_var) = expression;
476
477     return IHTMLWindow3_setTimeout(HTMLWINDOW3(This), &expr_var, msec, language, timerID);
478 }
479
480 static HRESULT WINAPI HTMLWindow2_clearTimeout(IHTMLWindow2 *iface, LONG timerID)
481 {
482     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
483
484     TRACE("(%p)->(%d)\n", This, timerID);
485
486     return clear_task_timer(&This->doc->basedoc, FALSE, timerID);
487 }
488
489 static HRESULT WINAPI HTMLWindow2_alert(IHTMLWindow2 *iface, BSTR message)
490 {
491     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
492     WCHAR wszTitle[100];
493
494     TRACE("(%p)->(%s)\n", This, debugstr_w(message));
495
496     if(!LoadStringW(get_shdoclc(), IDS_MESSAGE_BOX_TITLE, wszTitle,
497                     sizeof(wszTitle)/sizeof(WCHAR))) {
498         WARN("Could not load message box title: %d\n", GetLastError());
499         return S_OK;
500     }
501
502     MessageBoxW(This->doc_obj->hwnd, message, wszTitle, MB_ICONWARNING);
503     return S_OK;
504 }
505
506 static HRESULT WINAPI HTMLWindow2_confirm(IHTMLWindow2 *iface, BSTR message,
507         VARIANT_BOOL *confirmed)
508 {
509     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
510     WCHAR wszTitle[100];
511
512     TRACE("(%p)->(%s %p)\n", This, debugstr_w(message), confirmed);
513
514     if(!confirmed) return E_INVALIDARG;
515
516     if(!LoadStringW(get_shdoclc(), IDS_MESSAGE_BOX_TITLE, wszTitle,
517                 sizeof(wszTitle)/sizeof(WCHAR))) {
518         WARN("Could not load message box title: %d\n", GetLastError());
519         *confirmed = VARIANT_TRUE;
520         return S_OK;
521     }
522
523     if(MessageBoxW(This->doc_obj->hwnd, message, wszTitle,
524                 MB_OKCANCEL|MB_ICONQUESTION)==IDOK)
525         *confirmed = VARIANT_TRUE;
526     else *confirmed = VARIANT_FALSE;
527
528     return S_OK;
529 }
530
531 typedef struct
532 {
533     BSTR message;
534     BSTR dststr;
535     VARIANT *textdata;
536 }prompt_arg;
537
538 static INT_PTR CALLBACK prompt_dlgproc(HWND hwnd, UINT msg,
539         WPARAM wparam, LPARAM lparam)
540 {
541     switch(msg)
542     {
543         case WM_INITDIALOG:
544         {
545             prompt_arg *arg = (prompt_arg*)lparam;
546             WCHAR wszTitle[100];
547
548             if(!LoadStringW(get_shdoclc(), IDS_MESSAGE_BOX_TITLE, wszTitle,
549                         sizeof(wszTitle)/sizeof(WCHAR))) {
550                 WARN("Could not load message box title: %d\n", GetLastError());
551                 EndDialog(hwnd, wparam);
552                 return FALSE;
553             }
554
555             SetWindowLongPtrW(hwnd, DWLP_USER, lparam);
556             SetWindowTextW(hwnd, wszTitle);
557             SetWindowTextW(GetDlgItem(hwnd, ID_PROMPT_PROMPT), arg->message);
558             SetWindowTextW(GetDlgItem(hwnd, ID_PROMPT_EDIT), arg->dststr);
559             return FALSE;
560         }
561         case WM_COMMAND:
562             switch(wparam)
563             {
564                 case MAKEWPARAM(IDCANCEL, BN_CLICKED):
565                     EndDialog(hwnd, wparam);
566                     return TRUE;
567                 case MAKEWPARAM(IDOK, BN_CLICKED):
568                 {
569                     prompt_arg *arg =
570                         (prompt_arg*)GetWindowLongPtrW(hwnd, DWLP_USER);
571                     HWND hwndPrompt = GetDlgItem(hwnd, ID_PROMPT_EDIT);
572                     INT len = GetWindowTextLengthW(hwndPrompt);
573
574                     if(!arg->textdata)
575                     {
576                         EndDialog(hwnd, wparam);
577                         return TRUE;
578                     }
579
580                     V_VT(arg->textdata) = VT_BSTR;
581                     if(!len && !arg->dststr)
582                         V_BSTR(arg->textdata) = NULL;
583                     else
584                     {
585                         V_BSTR(arg->textdata) = SysAllocStringLen(NULL, len);
586                         GetWindowTextW(hwndPrompt, V_BSTR(arg->textdata), len+1);
587                     }
588                     EndDialog(hwnd, wparam);
589                     return TRUE;
590                 }
591             }
592             return FALSE;
593         case WM_CLOSE:
594             EndDialog(hwnd, IDCANCEL);
595             return TRUE;
596         default:
597             return FALSE;
598     }
599 }
600
601 static HRESULT WINAPI HTMLWindow2_prompt(IHTMLWindow2 *iface, BSTR message,
602         BSTR dststr, VARIANT *textdata)
603 {
604     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
605     prompt_arg arg;
606
607     TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(message), debugstr_w(dststr), textdata);
608
609     if(textdata) V_VT(textdata) = VT_NULL;
610
611     arg.message = message;
612     arg.dststr = dststr;
613     arg.textdata = textdata;
614
615     DialogBoxParamW(hInst, MAKEINTRESOURCEW(ID_PROMPT_DIALOG),
616             This->doc_obj->hwnd, prompt_dlgproc, (LPARAM)&arg);
617     return S_OK;
618 }
619
620 static HRESULT WINAPI HTMLWindow2_get_Image(IHTMLWindow2 *iface, IHTMLImageElementFactory **p)
621 {
622     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
623
624     TRACE("(%p)->(%p)\n", This, p);
625
626     if(!This->image_factory)
627         This->image_factory = HTMLImageElementFactory_Create(This);
628
629     *p = HTMLIMGFACTORY(This->image_factory);
630     IHTMLImageElementFactory_AddRef(*p);
631
632     return S_OK;
633 }
634
635 static HRESULT WINAPI HTMLWindow2_get_location(IHTMLWindow2 *iface, IHTMLLocation **p)
636 {
637     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
638     HTMLLocation *location;
639     HRESULT hres;
640
641     TRACE("(%p)->(%p)\n", This, p);
642
643     hres = get_location(This, &location);
644     if(FAILED(hres))
645         return hres;
646
647     *p = HTMLLOCATION(location);
648     return S_OK;
649 }
650
651 static HRESULT WINAPI HTMLWindow2_get_history(IHTMLWindow2 *iface, IOmHistory **p)
652 {
653     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
654     FIXME("(%p)->(%p)\n", This, p);
655     return E_NOTIMPL;
656 }
657
658 static HRESULT WINAPI HTMLWindow2_close(IHTMLWindow2 *iface)
659 {
660     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
661     FIXME("(%p)->()\n", This);
662     return E_NOTIMPL;
663 }
664
665 static HRESULT WINAPI HTMLWindow2_put_opener(IHTMLWindow2 *iface, VARIANT v)
666 {
667     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
668     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
669     return E_NOTIMPL;
670 }
671
672 static HRESULT WINAPI HTMLWindow2_get_opener(IHTMLWindow2 *iface, VARIANT *p)
673 {
674     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
675     FIXME("(%p)->(%p)\n", This, p);
676     return E_NOTIMPL;
677 }
678
679 static HRESULT WINAPI HTMLWindow2_get_navigator(IHTMLWindow2 *iface, IOmNavigator **p)
680 {
681     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
682
683     TRACE("(%p)->(%p)\n", This, p);
684
685     *p = OmNavigator_Create();
686     return S_OK;
687 }
688
689 static HRESULT WINAPI HTMLWindow2_put_name(IHTMLWindow2 *iface, BSTR v)
690 {
691     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
692     nsAString name_str;
693     nsresult nsres;
694
695     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
696
697     nsAString_Init(&name_str, v);
698     nsres = nsIDOMWindow_SetName(This->nswindow, &name_str);
699     nsAString_Finish(&name_str);
700     if(NS_FAILED(nsres))
701         ERR("SetName failed: %08x\n", nsres);
702
703     return S_OK;
704 }
705
706 static HRESULT WINAPI HTMLWindow2_get_name(IHTMLWindow2 *iface, BSTR *p)
707 {
708     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
709     nsAString name_str;
710     nsresult nsres;
711     HRESULT hres;
712
713     TRACE("(%p)->(%p)\n", This, p);
714
715     nsAString_Init(&name_str, NULL);
716     nsres = nsIDOMWindow_GetName(This->nswindow, &name_str);
717     if(NS_SUCCEEDED(nsres)) {
718         const PRUnichar *name;
719
720         nsAString_GetData(&name_str, &name);
721         if(*name) {
722             *p = SysAllocString(name);
723             hres = *p ? S_OK : E_OUTOFMEMORY;
724         }else {
725             *p = NULL;
726             hres = S_OK;
727         }
728     }else {
729         ERR("GetName failed: %08x\n", nsres);
730         hres = E_FAIL;
731     }
732     nsAString_Finish(&name_str);
733
734     return hres;
735 }
736
737 static HRESULT WINAPI HTMLWindow2_get_parent(IHTMLWindow2 *iface, IHTMLWindow2 **p)
738 {
739     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
740     TRACE("(%p)->(%p)\n", This, p);
741
742     if(This->parent) {
743         *p = HTMLWINDOW2(This->parent);
744         IHTMLWindow2_AddRef(*p);
745     }else
746         *p = NULL;
747
748     return S_OK;
749 }
750
751 static HRESULT WINAPI HTMLWindow2_open(IHTMLWindow2 *iface, BSTR url, BSTR name,
752          BSTR features, VARIANT_BOOL replace, IHTMLWindow2 **pomWindowResult)
753 {
754     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
755     FIXME("(%p)->(%s %s %s %x %p)\n", This, debugstr_w(url), debugstr_w(name),
756           debugstr_w(features), replace, pomWindowResult);
757     return E_NOTIMPL;
758 }
759
760 static HRESULT WINAPI HTMLWindow2_get_self(IHTMLWindow2 *iface, IHTMLWindow2 **p)
761 {
762     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
763
764     TRACE("(%p)->(%p)\n", This, p);
765
766     /* FIXME: We should return kind of proxy window here. */
767     IHTMLWindow2_AddRef(HTMLWINDOW2(This));
768     *p = HTMLWINDOW2(This);
769     return S_OK;
770 }
771
772 static HRESULT WINAPI HTMLWindow2_get_top(IHTMLWindow2 *iface, IHTMLWindow2 **p)
773 {
774     HTMLWindow *This = HTMLWINDOW2_THIS(iface), *curr;
775     TRACE("(%p)->(%p)\n", This, p);
776
777     curr = This;
778     while(curr->parent)
779         curr = curr->parent;
780     *p = HTMLWINDOW2(curr);
781     IHTMLWindow2_AddRef(*p);
782
783     return S_OK;
784 }
785
786 static HRESULT WINAPI HTMLWindow2_get_window(IHTMLWindow2 *iface, IHTMLWindow2 **p)
787 {
788     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
789
790     TRACE("(%p)->(%p)\n", This, p);
791
792     /* FIXME: We should return kind of proxy window here. */
793     IHTMLWindow2_AddRef(HTMLWINDOW2(This));
794     *p = HTMLWINDOW2(This);
795     return S_OK;
796 }
797
798 static HRESULT WINAPI HTMLWindow2_navigate(IHTMLWindow2 *iface, BSTR url)
799 {
800     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
801     FIXME("(%p)->(%s)\n", This, debugstr_w(url));
802     return E_NOTIMPL;
803 }
804
805 static HRESULT WINAPI HTMLWindow2_put_onfocus(IHTMLWindow2 *iface, VARIANT v)
806 {
807     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
808     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
809     return E_NOTIMPL;
810 }
811
812 static HRESULT WINAPI HTMLWindow2_get_onfocus(IHTMLWindow2 *iface, VARIANT *p)
813 {
814     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
815     FIXME("(%p)->(%p)\n", This, p);
816     return E_NOTIMPL;
817 }
818
819 static HRESULT WINAPI HTMLWindow2_put_onblur(IHTMLWindow2 *iface, VARIANT v)
820 {
821     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
822     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
823     return E_NOTIMPL;
824 }
825
826 static HRESULT WINAPI HTMLWindow2_get_onblur(IHTMLWindow2 *iface, VARIANT *p)
827 {
828     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
829     FIXME("(%p)->(%p)\n", This, p);
830     return E_NOTIMPL;
831 }
832
833 static HRESULT WINAPI HTMLWindow2_put_onload(IHTMLWindow2 *iface, VARIANT v)
834 {
835     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
836
837     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
838
839     return set_window_event(This, EVENTID_LOAD, &v);
840 }
841
842 static HRESULT WINAPI HTMLWindow2_get_onload(IHTMLWindow2 *iface, VARIANT *p)
843 {
844     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
845
846     TRACE("(%p)->(%p)\n", This, p);
847
848     return get_window_event(This, EVENTID_LOAD, p);
849 }
850
851 static HRESULT WINAPI HTMLWindow2_put_onbeforeunload(IHTMLWindow2 *iface, VARIANT v)
852 {
853     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
854
855     TRACE("(%p)->(v(%d))\n", This, V_VT(&v));
856
857     return set_window_event(This, EVENTID_BEFOREUNLOAD, &v);
858 }
859
860 static HRESULT WINAPI HTMLWindow2_get_onbeforeunload(IHTMLWindow2 *iface, VARIANT *p)
861 {
862     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
863
864     TRACE("(%p)->(%p)\n", This, p);
865
866     return get_window_event(This, EVENTID_BEFOREUNLOAD, p);
867 }
868
869 static HRESULT WINAPI HTMLWindow2_put_onunload(IHTMLWindow2 *iface, VARIANT v)
870 {
871     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
872     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
873     return E_NOTIMPL;
874 }
875
876 static HRESULT WINAPI HTMLWindow2_get_onunload(IHTMLWindow2 *iface, VARIANT *p)
877 {
878     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
879     FIXME("(%p)->(%p)\n", This, p);
880     return E_NOTIMPL;
881 }
882
883 static HRESULT WINAPI HTMLWindow2_put_onhelp(IHTMLWindow2 *iface, VARIANT v)
884 {
885     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
886     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
887     return E_NOTIMPL;
888 }
889
890 static HRESULT WINAPI HTMLWindow2_get_onhelp(IHTMLWindow2 *iface, VARIANT *p)
891 {
892     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
893     FIXME("(%p)->(%p)\n", This, p);
894     return E_NOTIMPL;
895 }
896
897 static HRESULT WINAPI HTMLWindow2_put_onerror(IHTMLWindow2 *iface, VARIANT v)
898 {
899     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
900     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
901     return E_NOTIMPL;
902 }
903
904 static HRESULT WINAPI HTMLWindow2_get_onerror(IHTMLWindow2 *iface, VARIANT *p)
905 {
906     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
907     FIXME("(%p)->(%p)\n", This, p);
908     return E_NOTIMPL;
909 }
910
911 static HRESULT WINAPI HTMLWindow2_put_onresize(IHTMLWindow2 *iface, VARIANT v)
912 {
913     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
914
915     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
916
917     return set_window_event(This, EVENTID_RESIZE, &v);
918 }
919
920 static HRESULT WINAPI HTMLWindow2_get_onresize(IHTMLWindow2 *iface, VARIANT *p)
921 {
922     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
923
924     TRACE("(%p)->(%p)\n", This, p);
925
926     return get_window_event(This, EVENTID_RESIZE, p);
927 }
928
929 static HRESULT WINAPI HTMLWindow2_put_onscroll(IHTMLWindow2 *iface, VARIANT v)
930 {
931     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
932     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
933     return E_NOTIMPL;
934 }
935
936 static HRESULT WINAPI HTMLWindow2_get_onscroll(IHTMLWindow2 *iface, VARIANT *p)
937 {
938     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
939     FIXME("(%p)->(%p)\n", This, p);
940     return E_NOTIMPL;
941 }
942
943 static HRESULT WINAPI HTMLWindow2_get_document(IHTMLWindow2 *iface, IHTMLDocument2 **p)
944 {
945     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
946
947     TRACE("(%p)->(%p)\n", This, p);
948
949     if(This->doc) {
950         /* FIXME: We should return a wrapper object here */
951         *p = HTMLDOC(&This->doc->basedoc);
952         IHTMLDocument2_AddRef(*p);
953     }else {
954         *p = NULL;
955     }
956
957     return S_OK;
958 }
959
960 static HRESULT WINAPI HTMLWindow2_get_event(IHTMLWindow2 *iface, IHTMLEventObj **p)
961 {
962     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
963
964     TRACE("(%p)->(%p)\n", This, p);
965
966     if(This->event)
967         IHTMLEventObj_AddRef(This->event);
968     *p = This->event;
969     return S_OK;
970 }
971
972 static HRESULT WINAPI HTMLWindow2_get__newEnum(IHTMLWindow2 *iface, IUnknown **p)
973 {
974     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
975     FIXME("(%p)->(%p)\n", This, p);
976     return E_NOTIMPL;
977 }
978
979 static HRESULT WINAPI HTMLWindow2_showModalDialog(IHTMLWindow2 *iface, BSTR dialog,
980         VARIANT *varArgIn, VARIANT *varOptions, VARIANT *varArgOut)
981 {
982     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
983     FIXME("(%p)->(%s %p %p %p)\n", This, debugstr_w(dialog), varArgIn, varOptions, varArgOut);
984     return E_NOTIMPL;
985 }
986
987 static HRESULT WINAPI HTMLWindow2_showHelp(IHTMLWindow2 *iface, BSTR helpURL, VARIANT helpArg,
988         BSTR features)
989 {
990     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
991     FIXME("(%p)->(%s v(%d) %s)\n", This, debugstr_w(helpURL), V_VT(&helpArg), debugstr_w(features));
992     return E_NOTIMPL;
993 }
994
995 static HRESULT WINAPI HTMLWindow2_get_screen(IHTMLWindow2 *iface, IHTMLScreen **p)
996 {
997     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
998
999     TRACE("(%p)->(%p)\n", This, p);
1000
1001     if(!This->screen) {
1002         HRESULT hres;
1003
1004         hres = HTMLScreen_Create(&This->screen);
1005         if(FAILED(hres))
1006             return hres;
1007     }
1008
1009     *p = This->screen;
1010     IHTMLScreen_AddRef(This->screen);
1011     return S_OK;
1012 }
1013
1014 static HRESULT WINAPI HTMLWindow2_get_Option(IHTMLWindow2 *iface, IHTMLOptionElementFactory **p)
1015 {
1016     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1017
1018     TRACE("(%p)->(%p)\n", This, p);
1019
1020     if(!This->option_factory)
1021         This->option_factory = HTMLOptionElementFactory_Create(This);
1022
1023     *p = HTMLOPTFACTORY(This->option_factory);
1024     IHTMLOptionElementFactory_AddRef(*p);
1025
1026     return S_OK;
1027 }
1028
1029 static HRESULT WINAPI HTMLWindow2_focus(IHTMLWindow2 *iface)
1030 {
1031     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1032     FIXME("(%p)->()\n", This);
1033     return E_NOTIMPL;
1034 }
1035
1036 static HRESULT WINAPI HTMLWindow2_get_closed(IHTMLWindow2 *iface, VARIANT_BOOL *p)
1037 {
1038     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1039     FIXME("(%p)->(%p)\n", This, p);
1040     return E_NOTIMPL;
1041 }
1042
1043 static HRESULT WINAPI HTMLWindow2_blur(IHTMLWindow2 *iface)
1044 {
1045     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1046     FIXME("(%p)->()\n", This);
1047     return E_NOTIMPL;
1048 }
1049
1050 static HRESULT WINAPI HTMLWindow2_scroll(IHTMLWindow2 *iface, LONG x, LONG y)
1051 {
1052     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1053     FIXME("(%p)->(%d %d)\n", This, x, y);
1054     return E_NOTIMPL;
1055 }
1056
1057 static HRESULT WINAPI HTMLWindow2_get_clientInformation(IHTMLWindow2 *iface, IOmNavigator **p)
1058 {
1059     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1060     FIXME("(%p)->(%p)\n", This, p);
1061     return E_NOTIMPL;
1062 }
1063
1064 static HRESULT WINAPI HTMLWindow2_setInterval(IHTMLWindow2 *iface, BSTR expression,
1065         LONG msec, VARIANT *language, LONG *timerID)
1066 {
1067     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1068     VARIANT expr;
1069
1070     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(expression), msec, language, timerID);
1071
1072     V_VT(&expr) = VT_BSTR;
1073     V_BSTR(&expr) = expression;
1074     return IHTMLWindow3_setInterval(HTMLWINDOW3(This), &expr, msec, language, timerID);
1075 }
1076
1077 static HRESULT WINAPI HTMLWindow2_clearInterval(IHTMLWindow2 *iface, LONG timerID)
1078 {
1079     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1080
1081     TRACE("(%p)->(%d)\n", This, timerID);
1082
1083     return clear_task_timer(&This->doc->basedoc, TRUE, timerID);
1084 }
1085
1086 static HRESULT WINAPI HTMLWindow2_put_offscreenBuffering(IHTMLWindow2 *iface, VARIANT v)
1087 {
1088     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1089     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
1090     return E_NOTIMPL;
1091 }
1092
1093 static HRESULT WINAPI HTMLWindow2_get_offscreenBuffering(IHTMLWindow2 *iface, VARIANT *p)
1094 {
1095     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1096     FIXME("(%p)->(%p)\n", This, p);
1097     return E_NOTIMPL;
1098 }
1099
1100 static HRESULT WINAPI HTMLWindow2_execScript(IHTMLWindow2 *iface, BSTR scode, BSTR language,
1101         VARIANT *pvarRet)
1102 {
1103     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1104     FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(scode), debugstr_w(language), pvarRet);
1105     return E_NOTIMPL;
1106 }
1107
1108 static HRESULT WINAPI HTMLWindow2_toString(IHTMLWindow2 *iface, BSTR *String)
1109 {
1110     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1111
1112     static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0};
1113
1114     TRACE("(%p)->(%p)\n", This, String);
1115
1116     if(!String)
1117         return E_INVALIDARG;
1118
1119     *String = SysAllocString(objectW);
1120     return *String ? S_OK : E_OUTOFMEMORY;
1121 }
1122
1123 static HRESULT WINAPI HTMLWindow2_scrollBy(IHTMLWindow2 *iface, LONG x, LONG y)
1124 {
1125     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1126     nsresult nsres;
1127
1128     TRACE("(%p)->(%d %d)\n", This, x, y);
1129
1130     nsres = nsIDOMWindow_ScrollBy(This->nswindow, x, y);
1131     if(NS_FAILED(nsres))
1132         ERR("ScrollBy failed: %08x\n", nsres);
1133
1134     return S_OK;
1135 }
1136
1137 static HRESULT WINAPI HTMLWindow2_scrollTo(IHTMLWindow2 *iface, LONG x, LONG y)
1138 {
1139     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1140     nsresult nsres;
1141
1142     TRACE("(%p)->(%d %d)\n", This, x, y);
1143
1144     nsres = nsIDOMWindow_ScrollTo(This->nswindow, x, y);
1145     if(NS_FAILED(nsres))
1146         ERR("ScrollTo failed: %08x\n", nsres);
1147
1148     return S_OK;
1149 }
1150
1151 static HRESULT WINAPI HTMLWindow2_moveTo(IHTMLWindow2 *iface, LONG x, LONG y)
1152 {
1153     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1154     FIXME("(%p)->(%d %d)\n", This, x, y);
1155     return E_NOTIMPL;
1156 }
1157
1158 static HRESULT WINAPI HTMLWindow2_moveBy(IHTMLWindow2 *iface, LONG x, LONG y)
1159 {
1160     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1161     FIXME("(%p)->(%d %d)\n", This, x, y);
1162     return E_NOTIMPL;
1163 }
1164
1165 static HRESULT WINAPI HTMLWindow2_resizeTo(IHTMLWindow2 *iface, LONG x, LONG y)
1166 {
1167     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1168     FIXME("(%p)->(%d %d)\n", This, x, y);
1169     return E_NOTIMPL;
1170 }
1171
1172 static HRESULT WINAPI HTMLWindow2_resizeBy(IHTMLWindow2 *iface, LONG x, LONG y)
1173 {
1174     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1175     FIXME("(%p)->(%d %d)\n", This, x, y);
1176     return E_NOTIMPL;
1177 }
1178
1179 static HRESULT WINAPI HTMLWindow2_get_external(IHTMLWindow2 *iface, IDispatch **p)
1180 {
1181     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1182
1183     TRACE("(%p)->(%p)\n", This, p);
1184
1185     *p = NULL;
1186
1187     if(!This->doc_obj->hostui)
1188         return S_OK;
1189
1190     return IDocHostUIHandler_GetExternal(This->doc_obj->hostui, p);
1191 }
1192
1193 static HRESULT HTMLWindow_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
1194         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1195 {
1196     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1197     global_prop_t *prop;
1198     DWORD idx;
1199     HRESULT hres;
1200
1201     idx = id - MSHTML_DISPID_CUSTOM_MIN;
1202     if(idx >= This->global_prop_cnt)
1203         return DISP_E_MEMBERNOTFOUND;
1204
1205     prop = This->global_props+idx;
1206
1207     switch(prop->type) {
1208     case GLOBAL_SCRIPTVAR: {
1209         IDispatchEx *dispex;
1210         IDispatch *disp;
1211
1212         disp = get_script_disp(prop->script_host);
1213         if(!disp)
1214             return E_UNEXPECTED;
1215
1216         hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
1217         if(SUCCEEDED(hres)) {
1218             TRACE("%s >>>\n", debugstr_w(prop->name));
1219             hres = IDispatchEx_InvokeEx(dispex, prop->id, lcid, flags, params, res, ei, caller);
1220             if(hres == S_OK)
1221                 TRACE("%s <<<\n", debugstr_w(prop->name));
1222             else
1223                 WARN("%s <<< %08x\n", debugstr_w(prop->name), hres);
1224             IDispatchEx_Release(dispex);
1225         }else {
1226             FIXME("No IDispatchEx\n");
1227         }
1228         IDispatch_Release(disp);
1229         break;
1230     }
1231     case GLOBAL_ELEMENTVAR: {
1232         IHTMLElement *elem;
1233
1234         hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), prop->name, &elem);
1235         if(FAILED(hres))
1236             return hres;
1237
1238         if(!elem)
1239             return DISP_E_MEMBERNOTFOUND;
1240
1241         V_VT(res) = VT_DISPATCH;
1242         V_DISPATCH(res) = (IDispatch*)elem;
1243         break;
1244     }
1245     default:
1246         ERR("invalid type %d\n", prop->type);
1247         hres = DISP_E_MEMBERNOTFOUND;
1248     }
1249
1250     return hres;
1251 }
1252
1253 #undef HTMLWINDOW2_THIS
1254
1255 static const IHTMLWindow2Vtbl HTMLWindow2Vtbl = {
1256     HTMLWindow2_QueryInterface,
1257     HTMLWindow2_AddRef,
1258     HTMLWindow2_Release,
1259     HTMLWindow2_GetTypeInfoCount,
1260     HTMLWindow2_GetTypeInfo,
1261     HTMLWindow2_GetIDsOfNames,
1262     HTMLWindow2_Invoke,
1263     HTMLWindow2_item,
1264     HTMLWindow2_get_length,
1265     HTMLWindow2_get_frames,
1266     HTMLWindow2_put_defaultStatus,
1267     HTMLWindow2_get_defaultStatus,
1268     HTMLWindow2_put_status,
1269     HTMLWindow2_get_status,
1270     HTMLWindow2_setTimeout,
1271     HTMLWindow2_clearTimeout,
1272     HTMLWindow2_alert,
1273     HTMLWindow2_confirm,
1274     HTMLWindow2_prompt,
1275     HTMLWindow2_get_Image,
1276     HTMLWindow2_get_location,
1277     HTMLWindow2_get_history,
1278     HTMLWindow2_close,
1279     HTMLWindow2_put_opener,
1280     HTMLWindow2_get_opener,
1281     HTMLWindow2_get_navigator,
1282     HTMLWindow2_put_name,
1283     HTMLWindow2_get_name,
1284     HTMLWindow2_get_parent,
1285     HTMLWindow2_open,
1286     HTMLWindow2_get_self,
1287     HTMLWindow2_get_top,
1288     HTMLWindow2_get_window,
1289     HTMLWindow2_navigate,
1290     HTMLWindow2_put_onfocus,
1291     HTMLWindow2_get_onfocus,
1292     HTMLWindow2_put_onblur,
1293     HTMLWindow2_get_onblur,
1294     HTMLWindow2_put_onload,
1295     HTMLWindow2_get_onload,
1296     HTMLWindow2_put_onbeforeunload,
1297     HTMLWindow2_get_onbeforeunload,
1298     HTMLWindow2_put_onunload,
1299     HTMLWindow2_get_onunload,
1300     HTMLWindow2_put_onhelp,
1301     HTMLWindow2_get_onhelp,
1302     HTMLWindow2_put_onerror,
1303     HTMLWindow2_get_onerror,
1304     HTMLWindow2_put_onresize,
1305     HTMLWindow2_get_onresize,
1306     HTMLWindow2_put_onscroll,
1307     HTMLWindow2_get_onscroll,
1308     HTMLWindow2_get_document,
1309     HTMLWindow2_get_event,
1310     HTMLWindow2_get__newEnum,
1311     HTMLWindow2_showModalDialog,
1312     HTMLWindow2_showHelp,
1313     HTMLWindow2_get_screen,
1314     HTMLWindow2_get_Option,
1315     HTMLWindow2_focus,
1316     HTMLWindow2_get_closed,
1317     HTMLWindow2_blur,
1318     HTMLWindow2_scroll,
1319     HTMLWindow2_get_clientInformation,
1320     HTMLWindow2_setInterval,
1321     HTMLWindow2_clearInterval,
1322     HTMLWindow2_put_offscreenBuffering,
1323     HTMLWindow2_get_offscreenBuffering,
1324     HTMLWindow2_execScript,
1325     HTMLWindow2_toString,
1326     HTMLWindow2_scrollBy,
1327     HTMLWindow2_scrollTo,
1328     HTMLWindow2_moveTo,
1329     HTMLWindow2_moveBy,
1330     HTMLWindow2_resizeTo,
1331     HTMLWindow2_resizeBy,
1332     HTMLWindow2_get_external
1333 };
1334
1335 #define HTMLWINDOW3_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow3, iface)
1336
1337 static HRESULT WINAPI HTMLWindow3_QueryInterface(IHTMLWindow3 *iface, REFIID riid, void **ppv)
1338 {
1339     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1340
1341     return IHTMLWindow2_QueryInterface(HTMLWINDOW2(This), riid, ppv);
1342 }
1343
1344 static ULONG WINAPI HTMLWindow3_AddRef(IHTMLWindow3 *iface)
1345 {
1346     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1347
1348     return IHTMLWindow2_AddRef(HTMLWINDOW2(This));
1349 }
1350
1351 static ULONG WINAPI HTMLWindow3_Release(IHTMLWindow3 *iface)
1352 {
1353     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1354
1355     return IHTMLWindow2_Release(HTMLWINDOW2(This));
1356 }
1357
1358 static HRESULT WINAPI HTMLWindow3_GetTypeInfoCount(IHTMLWindow3 *iface, UINT *pctinfo)
1359 {
1360     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1361
1362     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
1363 }
1364
1365 static HRESULT WINAPI HTMLWindow3_GetTypeInfo(IHTMLWindow3 *iface, UINT iTInfo,
1366                                               LCID lcid, ITypeInfo **ppTInfo)
1367 {
1368     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1369
1370     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
1371 }
1372
1373 static HRESULT WINAPI HTMLWindow3_GetIDsOfNames(IHTMLWindow3 *iface, REFIID riid,
1374                                                 LPOLESTR *rgszNames, UINT cNames,
1375                                                 LCID lcid, DISPID *rgDispId)
1376 {
1377     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1378
1379     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
1380 }
1381
1382 static HRESULT WINAPI HTMLWindow3_Invoke(IHTMLWindow3 *iface, DISPID dispIdMember,
1383                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1384                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1385 {
1386     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1387
1388     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
1389             pVarResult, pExcepInfo, puArgErr);
1390 }
1391
1392 static HRESULT WINAPI HTMLWindow3_get_screenLeft(IHTMLWindow3 *iface, LONG *p)
1393 {
1394     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1395     FIXME("(%p)->(%p)\n", This, p);
1396     return E_NOTIMPL;
1397 }
1398
1399 static HRESULT WINAPI HTMLWindow3_get_screenTop(IHTMLWindow3 *iface, LONG *p)
1400 {
1401     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1402     FIXME("(%p)->(%p)\n", This, p);
1403     return E_NOTIMPL;
1404 }
1405
1406 static HRESULT WINAPI HTMLWindow3_attachEvent(IHTMLWindow3 *iface, BSTR event, IDispatch *pDisp, VARIANT_BOOL *pfResult)
1407 {
1408     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1409
1410     TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(event), pDisp, pfResult);
1411
1412     if(!This->doc) {
1413         FIXME("No document\n");
1414         return E_FAIL;
1415     }
1416
1417     return attach_event(&This->doc->body_event_target, &This->doc->basedoc, event, pDisp, pfResult);
1418 }
1419
1420 static HRESULT WINAPI HTMLWindow3_detachEvent(IHTMLWindow3 *iface, BSTR event, IDispatch *pDisp)
1421 {
1422     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1423     FIXME("(%p)->()\n", This);
1424     return E_NOTIMPL;
1425 }
1426
1427 static HRESULT window_set_timer(HTMLWindow *This, VARIANT *expr, LONG msec, VARIANT *language,
1428         BOOL interval, LONG *timer_id)
1429 {
1430     IDispatch *disp = NULL;
1431
1432     switch(V_VT(expr)) {
1433     case VT_DISPATCH:
1434         disp = V_DISPATCH(expr);
1435         IDispatch_AddRef(disp);
1436         break;
1437
1438     case VT_BSTR:
1439         disp = script_parse_event(This, V_BSTR(expr));
1440         break;
1441
1442     default:
1443         FIXME("unimplemented vt=%d\n", V_VT(expr));
1444         return E_NOTIMPL;
1445     }
1446
1447     if(!disp)
1448         return E_FAIL;
1449
1450     *timer_id = set_task_timer(&This->doc->basedoc, msec, interval, disp);
1451     IDispatch_Release(disp);
1452
1453     return S_OK;
1454 }
1455
1456 static HRESULT WINAPI HTMLWindow3_setTimeout(IHTMLWindow3 *iface, VARIANT *expression, LONG msec,
1457         VARIANT *language, LONG *timerID)
1458 {
1459     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1460
1461     TRACE("(%p)->(%p(%d) %d %p %p)\n", This, expression, V_VT(expression), msec, language, timerID);
1462
1463     return window_set_timer(This, expression, msec, language, FALSE, timerID);
1464 }
1465
1466 static HRESULT WINAPI HTMLWindow3_setInterval(IHTMLWindow3 *iface, VARIANT *expression, LONG msec,
1467         VARIANT *language, LONG *timerID)
1468 {
1469     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1470
1471     TRACE("(%p)->(%p %d %p %p)\n", This, expression, msec, language, timerID);
1472
1473     return window_set_timer(This, expression, msec, language, TRUE, timerID);
1474 }
1475
1476 static HRESULT WINAPI HTMLWindow3_print(IHTMLWindow3 *iface)
1477 {
1478     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1479     FIXME("(%p)\n", This);
1480     return E_NOTIMPL;
1481 }
1482
1483 static HRESULT WINAPI HTMLWindow3_put_onbeforeprint(IHTMLWindow3 *iface, VARIANT v)
1484 {
1485     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1486     FIXME("(%p)->()\n", This);
1487     return E_NOTIMPL;
1488 }
1489
1490 static HRESULT WINAPI HTMLWindow3_get_onbeforeprint(IHTMLWindow3 *iface, VARIANT *p)
1491 {
1492     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1493     FIXME("(%p)->(%p)\n", This, p);
1494     return E_NOTIMPL;
1495 }
1496
1497 static HRESULT WINAPI HTMLWindow3_put_onafterprint(IHTMLWindow3 *iface, VARIANT v)
1498 {
1499     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1500     FIXME("(%p)->()\n", This);
1501     return E_NOTIMPL;
1502 }
1503
1504 static HRESULT WINAPI HTMLWindow3_get_onafterprint(IHTMLWindow3 *iface, VARIANT *p)
1505 {
1506     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1507     FIXME("(%p)->(%p)\n", This, p);
1508     return E_NOTIMPL;
1509 }
1510
1511 static HRESULT WINAPI HTMLWindow3_get_clipboardData(IHTMLWindow3 *iface, IHTMLDataTransfer **p)
1512 {
1513     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1514     FIXME("(%p)->(%p)\n", This, p);
1515     return E_NOTIMPL;
1516 }
1517
1518 static HRESULT WINAPI HTMLWindow3_showModelessDialog(IHTMLWindow3 *iface, BSTR url,
1519         VARIANT *varArgIn, VARIANT *options, IHTMLWindow2 **pDialog)
1520 {
1521     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1522     FIXME("(%p)->(%s %p %p %p)\n", This, debugstr_w(url), varArgIn, options, pDialog);
1523     return E_NOTIMPL;
1524 }
1525
1526 #undef HTMLWINDOW3_THIS
1527
1528 static const IHTMLWindow3Vtbl HTMLWindow3Vtbl = {
1529     HTMLWindow3_QueryInterface,
1530     HTMLWindow3_AddRef,
1531     HTMLWindow3_Release,
1532     HTMLWindow3_GetTypeInfoCount,
1533     HTMLWindow3_GetTypeInfo,
1534     HTMLWindow3_GetIDsOfNames,
1535     HTMLWindow3_Invoke,
1536     HTMLWindow3_get_screenLeft,
1537     HTMLWindow3_get_screenTop,
1538     HTMLWindow3_attachEvent,
1539     HTMLWindow3_detachEvent,
1540     HTMLWindow3_setTimeout,
1541     HTMLWindow3_setInterval,
1542     HTMLWindow3_print,
1543     HTMLWindow3_put_onbeforeprint,
1544     HTMLWindow3_get_onbeforeprint,
1545     HTMLWindow3_put_onafterprint,
1546     HTMLWindow3_get_onafterprint,
1547     HTMLWindow3_get_clipboardData,
1548     HTMLWindow3_showModelessDialog
1549 };
1550
1551 #define HTMLWINDOW4_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow4, iface)
1552
1553 static HRESULT WINAPI HTMLWindow4_QueryInterface(IHTMLWindow4 *iface, REFIID riid, void **ppv)
1554 {
1555     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1556
1557     return IHTMLWindow2_QueryInterface(HTMLWINDOW2(This), riid, ppv);
1558 }
1559
1560 static ULONG WINAPI HTMLWindow4_AddRef(IHTMLWindow4 *iface)
1561 {
1562     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1563
1564     return IHTMLWindow2_AddRef(HTMLWINDOW2(This));
1565 }
1566
1567 static ULONG WINAPI HTMLWindow4_Release(IHTMLWindow4 *iface)
1568 {
1569     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1570
1571     return IHTMLWindow2_Release(HTMLWINDOW2(This));
1572 }
1573
1574 static HRESULT WINAPI HTMLWindow4_GetTypeInfoCount(IHTMLWindow4 *iface, UINT *pctinfo)
1575 {
1576     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1577
1578     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
1579 }
1580
1581 static HRESULT WINAPI HTMLWindow4_GetTypeInfo(IHTMLWindow4 *iface, UINT iTInfo,
1582                                               LCID lcid, ITypeInfo **ppTInfo)
1583 {
1584     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1585
1586     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
1587 }
1588
1589 static HRESULT WINAPI HTMLWindow4_GetIDsOfNames(IHTMLWindow4 *iface, REFIID riid,
1590                                                 LPOLESTR *rgszNames, UINT cNames,
1591                                                 LCID lcid, DISPID *rgDispId)
1592 {
1593     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1594
1595     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
1596 }
1597
1598 static HRESULT WINAPI HTMLWindow4_Invoke(IHTMLWindow4 *iface, DISPID dispIdMember,
1599                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1600                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1601 {
1602     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1603
1604     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
1605             pVarResult, pExcepInfo, puArgErr);
1606 }
1607
1608 static HRESULT WINAPI HTMLWindow4_createPopup(IHTMLWindow4 *iface, VARIANT *varArgIn,
1609                             IDispatch **ppPopup)
1610 {
1611     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1612     FIXME("(%p)->(%p %p)\n", This, varArgIn, ppPopup);
1613     return E_NOTIMPL;
1614 }
1615
1616 static HRESULT WINAPI HTMLWindow4_get_frameElement(IHTMLWindow4 *iface, IHTMLFrameBase **p)
1617 {
1618     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1619     TRACE("(%p)->(%p)\n", This, p);
1620
1621     if(This->frame_element) {
1622         *p = HTMLFRAMEBASE(This->frame_element);
1623         IHTMLFrameBase_AddRef(*p);
1624     }else
1625         *p = NULL;
1626
1627     return S_OK;
1628 }
1629
1630 #undef HTMLWINDOW4_THIS
1631
1632 static const IHTMLWindow4Vtbl HTMLWindow4Vtbl = {
1633     HTMLWindow4_QueryInterface,
1634     HTMLWindow4_AddRef,
1635     HTMLWindow4_Release,
1636     HTMLWindow4_GetTypeInfoCount,
1637     HTMLWindow4_GetTypeInfo,
1638     HTMLWindow4_GetIDsOfNames,
1639     HTMLWindow4_Invoke,
1640     HTMLWindow4_createPopup,
1641     HTMLWindow4_get_frameElement
1642 };
1643
1644 #define DISPEX_THIS(iface) DEFINE_THIS(HTMLWindow, IDispatchEx, iface)
1645
1646 static HRESULT WINAPI WindowDispEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
1647 {
1648     HTMLWindow *This = DISPEX_THIS(iface);
1649
1650     return IHTMLWindow2_QueryInterface(HTMLWINDOW2(This), riid, ppv);
1651 }
1652
1653 static ULONG WINAPI WindowDispEx_AddRef(IDispatchEx *iface)
1654 {
1655     HTMLWindow *This = DISPEX_THIS(iface);
1656
1657     return IHTMLWindow2_AddRef(HTMLWINDOW2(This));
1658 }
1659
1660 static ULONG WINAPI WindowDispEx_Release(IDispatchEx *iface)
1661 {
1662     HTMLWindow *This = DISPEX_THIS(iface);
1663
1664     return IHTMLWindow2_Release(HTMLWINDOW2(This));
1665 }
1666
1667 static HRESULT WINAPI WindowDispEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
1668 {
1669     HTMLWindow *This = DISPEX_THIS(iface);
1670
1671     TRACE("(%p)->(%p)\n", This, pctinfo);
1672
1673     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
1674 }
1675
1676 static HRESULT WINAPI WindowDispEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
1677                                                LCID lcid, ITypeInfo **ppTInfo)
1678 {
1679     HTMLWindow *This = DISPEX_THIS(iface);
1680
1681     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1682
1683     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
1684 }
1685
1686 static HRESULT WINAPI WindowDispEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
1687                                                  LPOLESTR *rgszNames, UINT cNames,
1688                                                  LCID lcid, DISPID *rgDispId)
1689 {
1690     HTMLWindow *This = DISPEX_THIS(iface);
1691
1692     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1693           lcid, rgDispId);
1694
1695     /* FIXME: Use script dispatch */
1696
1697     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
1698 }
1699
1700 static HRESULT WINAPI WindowDispEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
1701                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1702                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1703 {
1704     HTMLWindow *This = DISPEX_THIS(iface);
1705
1706     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1707           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1708
1709     /* FIXME: Use script dispatch */
1710
1711     return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid, wFlags, pDispParams,
1712                               pVarResult, pExcepInfo, puArgErr);
1713 }
1714
1715 static global_prop_t *alloc_global_prop(HTMLWindow *This, global_prop_type_t type, BSTR name)
1716 {
1717     if(This->global_prop_cnt == This->global_prop_size) {
1718         global_prop_t *new_props;
1719         DWORD new_size;
1720
1721         if(This->global_props) {
1722             new_size = This->global_prop_size*2;
1723             new_props = heap_realloc(This->global_props, new_size*sizeof(global_prop_t));
1724         }else {
1725             new_size = 16;
1726             new_props = heap_alloc(new_size*sizeof(global_prop_t));
1727         }
1728         if(!new_props)
1729             return NULL;
1730         This->global_props = new_props;
1731         This->global_prop_size = new_size;
1732     }
1733
1734     This->global_props[This->global_prop_cnt].name = heap_strdupW(name);
1735     if(!This->global_props[This->global_prop_cnt].name)
1736         return NULL;
1737
1738     This->global_props[This->global_prop_cnt].type = type;
1739     return This->global_props + This->global_prop_cnt++;
1740 }
1741
1742 static inline DWORD prop_to_dispid(HTMLWindow *This, global_prop_t *prop)
1743 {
1744     return MSHTML_DISPID_CUSTOM_MIN + (prop-This->global_props);
1745 }
1746
1747 HRESULT search_window_props(HTMLWindow *This, BSTR bstrName, DWORD grfdex, DISPID *pid)
1748 {
1749     DWORD i;
1750     ScriptHost *script_host;
1751     DISPID id;
1752
1753     for(i=0; i < This->global_prop_cnt; i++) {
1754         /* FIXME: case sensitivity */
1755         if(!strcmpW(This->global_props[i].name, bstrName)) {
1756             *pid = MSHTML_DISPID_CUSTOM_MIN+i;
1757             return S_OK;
1758         }
1759     }
1760
1761     if(find_global_prop(This, bstrName, grfdex, &script_host, &id)) {
1762         global_prop_t *prop;
1763
1764         prop = alloc_global_prop(This, GLOBAL_SCRIPTVAR, bstrName);
1765         if(!prop)
1766             return E_OUTOFMEMORY;
1767
1768         prop->script_host = script_host;
1769         prop->id = id;
1770
1771         *pid = prop_to_dispid(This, prop);
1772         return S_OK;
1773     }
1774
1775     return DISP_E_UNKNOWNNAME;
1776 }
1777
1778 static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
1779 {
1780     HTMLWindow *This = DISPEX_THIS(iface);
1781     HRESULT hres;
1782
1783     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
1784
1785     hres = search_window_props(This, bstrName, grfdex, pid);
1786     if(hres != DISP_E_UNKNOWNNAME)
1787         return hres;
1788
1789     hres = IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
1790     if(hres != DISP_E_UNKNOWNNAME)
1791         return hres;
1792
1793     if(This->doc) {
1794         global_prop_t *prop;
1795         IHTMLElement *elem;
1796
1797         hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), bstrName, &elem);
1798         if(SUCCEEDED(hres) && elem) {
1799             IHTMLElement_Release(elem);
1800
1801             prop = alloc_global_prop(This, GLOBAL_ELEMENTVAR, bstrName);
1802             if(!prop)
1803                 return E_OUTOFMEMORY;
1804
1805             *pid = prop_to_dispid(This, prop);
1806             return S_OK;
1807         }
1808     }
1809
1810     return DISP_E_UNKNOWNNAME;
1811 }
1812
1813 static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1814         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1815 {
1816     HTMLWindow *This = DISPEX_THIS(iface);
1817
1818     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1819
1820     if(id == DISPID_IHTMLWINDOW2_LOCATION && (wFlags & DISPATCH_PROPERTYPUT)) {
1821         HTMLLocation *location;
1822         HRESULT hres;
1823
1824         TRACE("forwarding to location.href\n");
1825
1826         hres = get_location(This, &location);
1827         if(FAILED(hres))
1828             return hres;
1829
1830         hres = IDispatchEx_InvokeEx(DISPATCHEX(&location->dispex), DISPID_VALUE, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1831         IHTMLLocation_Release(HTMLLOCATION(location));
1832         return hres;
1833     }
1834
1835     return IDispatchEx_InvokeEx(DISPATCHEX(&This->dispex), id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1836 }
1837
1838 static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
1839 {
1840     HTMLWindow *This = DISPEX_THIS(iface);
1841
1842     TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
1843
1844     return IDispatchEx_DeleteMemberByName(DISPATCHEX(&This->dispex), bstrName, grfdex);
1845 }
1846
1847 static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
1848 {
1849     HTMLWindow *This = DISPEX_THIS(iface);
1850
1851     TRACE("(%p)->(%x)\n", This, id);
1852
1853     return IDispatchEx_DeleteMemberByDispID(DISPATCHEX(&This->dispex), id);
1854 }
1855
1856 static HRESULT WINAPI WindowDispEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
1857 {
1858     HTMLWindow *This = DISPEX_THIS(iface);
1859
1860     TRACE("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex);
1861
1862     return IDispatchEx_GetMemberProperties(DISPATCHEX(&This->dispex), id, grfdexFetch, pgrfdex);
1863 }
1864
1865 static HRESULT WINAPI WindowDispEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
1866 {
1867     HTMLWindow *This = DISPEX_THIS(iface);
1868
1869     TRACE("(%p)->(%x %p)\n", This, id, pbstrName);
1870
1871     return IDispatchEx_GetMemberName(DISPATCHEX(&This->dispex), id, pbstrName);
1872 }
1873
1874 static HRESULT WINAPI WindowDispEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
1875 {
1876     HTMLWindow *This = DISPEX_THIS(iface);
1877
1878     TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
1879
1880     return IDispatchEx_GetNextDispID(DISPATCHEX(&This->dispex), grfdex, id, pid);
1881 }
1882
1883 static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
1884 {
1885     HTMLWindow *This = DISPEX_THIS(iface);
1886
1887     TRACE("(%p)->(%p)\n", This, ppunk);
1888
1889     *ppunk = NULL;
1890     return S_OK;
1891 }
1892
1893 #undef DISPEX_THIS
1894
1895 static const IDispatchExVtbl WindowDispExVtbl = {
1896     WindowDispEx_QueryInterface,
1897     WindowDispEx_AddRef,
1898     WindowDispEx_Release,
1899     WindowDispEx_GetTypeInfoCount,
1900     WindowDispEx_GetTypeInfo,
1901     WindowDispEx_GetIDsOfNames,
1902     WindowDispEx_Invoke,
1903     WindowDispEx_GetDispID,
1904     WindowDispEx_InvokeEx,
1905     WindowDispEx_DeleteMemberByName,
1906     WindowDispEx_DeleteMemberByDispID,
1907     WindowDispEx_GetMemberProperties,
1908     WindowDispEx_GetMemberName,
1909     WindowDispEx_GetNextDispID,
1910     WindowDispEx_GetNameSpaceParent
1911 };
1912
1913 static const tid_t HTMLWindow_iface_tids[] = {
1914     IHTMLWindow2_tid,
1915     IHTMLWindow3_tid,
1916     IHTMLWindow4_tid,
1917     0
1918 };
1919
1920 static const dispex_static_data_vtbl_t HTMLWindow_dispex_vtbl = {
1921     NULL,
1922     NULL,
1923     HTMLWindow_invoke
1924 };
1925
1926 static dispex_static_data_t HTMLWindow_dispex = {
1927     &HTMLWindow_dispex_vtbl,
1928     DispHTMLWindow2_tid,
1929     NULL,
1930     HTMLWindow_iface_tids
1931 };
1932
1933 HRESULT HTMLWindow_Create(HTMLDocumentObj *doc_obj, nsIDOMWindow *nswindow, HTMLWindow *parent, HTMLWindow **ret)
1934 {
1935     HTMLWindow *window;
1936
1937     window = heap_alloc_zero(sizeof(HTMLWindow));
1938     if(!window)
1939         return E_OUTOFMEMORY;
1940
1941     window->window_ref = heap_alloc(sizeof(windowref_t));
1942     if(!window->window_ref) {
1943         heap_free(window);
1944         return E_OUTOFMEMORY;
1945     }
1946
1947     window->lpHTMLWindow2Vtbl = &HTMLWindow2Vtbl;
1948     window->lpHTMLWindow3Vtbl = &HTMLWindow3Vtbl;
1949     window->lpHTMLWindow4Vtbl = &HTMLWindow4Vtbl;
1950     window->lpIDispatchExVtbl = &WindowDispExVtbl;
1951     window->ref = 1;
1952     window->doc_obj = doc_obj;
1953
1954     window->window_ref->window = window;
1955     window->window_ref->ref = 1;
1956
1957     init_dispex(&window->dispex, (IUnknown*)HTMLWINDOW2(window), &HTMLWindow_dispex);
1958
1959     if(nswindow) {
1960         nsIDOMWindow_AddRef(nswindow);
1961         window->nswindow = nswindow;
1962     }
1963
1964     window->scriptmode = parent ? parent->scriptmode : SCRIPTMODE_GECKO;
1965     window->readystate = READYSTATE_UNINITIALIZED;
1966     list_init(&window->script_hosts);
1967
1968     window->task_magic = get_task_target_magic();
1969     update_window_doc(window);
1970
1971     list_init(&window->children);
1972     list_add_head(&window_list, &window->entry);
1973
1974     if(parent) {
1975         IHTMLWindow2_AddRef(HTMLWINDOW2(window));
1976
1977         window->parent = parent;
1978         list_add_tail(&parent->children, &window->sibling_entry);
1979     }
1980
1981     *ret = window;
1982     return S_OK;
1983 }
1984
1985 void update_window_doc(HTMLWindow *window)
1986 {
1987     nsIDOMHTMLDocument *nshtmldoc;
1988     nsIDOMDocument *nsdoc;
1989     nsresult nsres;
1990
1991     nsres = nsIDOMWindow_GetDocument(window->nswindow, &nsdoc);
1992     if(NS_FAILED(nsres) || !nsdoc) {
1993         ERR("GetDocument failed: %08x\n", nsres);
1994         return;
1995     }
1996
1997     nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMHTMLDocument, (void**)&nshtmldoc);
1998     nsIDOMDocument_Release(nsdoc);
1999     if(NS_FAILED(nsres)) {
2000         ERR("Could not get nsIDOMHTMLDocument iface: %08x\n", nsres);
2001         return;
2002     }
2003
2004     if(!window->doc || window->doc->nsdoc != nshtmldoc) {
2005         HTMLDocumentNode *doc;
2006         HRESULT hres;
2007
2008         hres = create_doc_from_nsdoc(nshtmldoc, window->doc_obj, window, &doc);
2009         if(SUCCEEDED(hres)) {
2010             window_set_docnode(window, doc);
2011             htmldoc_release(&doc->basedoc);
2012         }else {
2013             ERR("create_doc_from_nsdoc failed: %08x\n", hres);
2014         }
2015     }
2016
2017     nsIDOMHTMLDocument_Release(nshtmldoc);
2018 }
2019
2020 HTMLWindow *nswindow_to_window(const nsIDOMWindow *nswindow)
2021 {
2022     HTMLWindow *iter;
2023
2024     LIST_FOR_EACH_ENTRY(iter, &window_list, HTMLWindow, entry) {
2025         if(iter->nswindow == nswindow)
2026             return iter;
2027     }
2028
2029     return NULL;
2030 }