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