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