mshtml: Removed duplicate condition (Coverity).
[wine] / dlls / mshtml / script.c
1 /*
2  * Copyright 2008 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 "config.h"
20
21 #include <stdarg.h>
22 #include <assert.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "activscp.h"
31 #include "activdbg.h"
32
33 #include "wine/debug.h"
34
35 #include "mshtml_private.h"
36 #include "pluginhost.h"
37 #include "htmlevent.h"
38 #include "binding.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
41
42 #ifdef _WIN64
43
44 #define CTXARG_T DWORDLONG
45 #define IActiveScriptSiteDebugVtbl IActiveScriptSiteDebug64Vtbl
46
47 #define IActiveScriptParse_Release IActiveScriptParse64_Release
48 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
49 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
50 #define IActiveScriptParseProcedure_Release IActiveScriptParseProcedure64_Release
51 #define IActiveScriptParseProcedure_ParseProcedureText IActiveScriptParseProcedure64_ParseProcedureText
52
53 #else
54
55 #define CTXARG_T DWORD
56 #define IActiveScriptSiteDebugVtbl IActiveScriptSiteDebug32Vtbl
57
58 #define IActiveScriptParse_Release IActiveScriptParse32_Release
59 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
60 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
61 #define IActiveScriptParseProcedure_Release IActiveScriptParseProcedure32_Release
62 #define IActiveScriptParseProcedure_ParseProcedureText IActiveScriptParseProcedure32_ParseProcedureText
63
64 #endif
65
66 static const WCHAR documentW[] = {'d','o','c','u','m','e','n','t',0};
67 static const WCHAR windowW[] = {'w','i','n','d','o','w',0};
68 static const WCHAR script_endW[] = {'<','/','S','C','R','I','P','T','>',0};
69 static const WCHAR emptyW[] = {0};
70
71 struct ScriptHost {
72     IActiveScriptSite              IActiveScriptSite_iface;
73     IActiveScriptSiteInterruptPoll IActiveScriptSiteInterruptPoll_iface;
74     IActiveScriptSiteWindow        IActiveScriptSiteWindow_iface;
75     IActiveScriptSiteUIControl     IActiveScriptSiteUIControl_iface;
76     IActiveScriptSiteDebug         IActiveScriptSiteDebug_iface;
77     IServiceProvider               IServiceProvider_iface;
78
79     LONG ref;
80
81     IActiveScript *script;
82     IActiveScriptParse *parse;
83     IActiveScriptParseProcedure *parse_proc;
84
85     SCRIPTSTATE script_state;
86
87     HTMLInnerWindow *window;
88
89     GUID guid;
90     struct list entry;
91 };
92
93 static void set_script_prop(ScriptHost *script_host, DWORD property, VARIANT *val)
94 {
95     IActiveScriptProperty *script_prop;
96     HRESULT hres;
97
98     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptProperty,
99             (void**)&script_prop);
100     if(FAILED(hres)) {
101         WARN("Could not get IActiveScriptProperty iface: %08x\n", hres);
102         return;
103     }
104
105     hres = IActiveScriptProperty_SetProperty(script_prop, property, NULL, val);
106     IActiveScriptProperty_Release(script_prop);
107     if(FAILED(hres))
108         WARN("SetProperty(%x) failed: %08x\n", property, hres);
109 }
110
111 static BOOL init_script_engine(ScriptHost *script_host)
112 {
113     IObjectSafety *safety;
114     SCRIPTSTATE state;
115     DWORD supported_opts=0, enabled_opts=0;
116     VARIANT var;
117     HRESULT hres;
118
119     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParse, (void**)&script_host->parse);
120     if(FAILED(hres)) {
121         WARN("Could not get IActiveScriptHost: %08x\n", hres);
122         return FALSE;
123     }
124
125     hres = IActiveScript_QueryInterface(script_host->script, &IID_IObjectSafety, (void**)&safety);
126     if(FAILED(hres)) {
127         FIXME("Could not get IObjectSafety: %08x\n", hres);
128         return FALSE;
129     }
130
131     hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported_opts, &enabled_opts);
132     if(FAILED(hres)) {
133         FIXME("GetInterfaceSafetyOptions failed: %08x\n", hres);
134     }else if(!(supported_opts & INTERFACE_USES_DISPEX)) {
135         FIXME("INTERFACE_USES_DISPEX is not supported\n");
136     }else {
137         hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse,
138                 INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER,
139                 INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER);
140         if(FAILED(hres))
141             FIXME("SetInterfaceSafetyOptions failed: %08x\n", hres);
142     }
143
144     IObjectSafety_Release(safety);
145     if(FAILED(hres))
146         return FALSE;
147
148     V_VT(&var) = VT_I4;
149     V_I4(&var) = 1;
150     set_script_prop(script_host, SCRIPTPROP_INVOKEVERSIONING, &var);
151
152     V_VT(&var) = VT_BOOL;
153     V_BOOL(&var) = VARIANT_TRUE;
154     set_script_prop(script_host, SCRIPTPROP_HACK_TRIDENTEVENTSINK, &var);
155
156     hres = IActiveScriptParse_InitNew(script_host->parse);
157     if(FAILED(hres)) {
158         WARN("InitNew failed: %08x\n", hres);
159         return FALSE;
160     }
161
162     hres = IActiveScript_SetScriptSite(script_host->script, &script_host->IActiveScriptSite_iface);
163     if(FAILED(hres)) {
164         WARN("SetScriptSite failed: %08x\n", hres);
165         IActiveScript_Close(script_host->script);
166         return FALSE;
167     }
168
169     hres = IActiveScript_GetScriptState(script_host->script, &state);
170     if(FAILED(hres))
171         WARN("GetScriptState failed: %08x\n", hres);
172     else if(state != SCRIPTSTATE_INITIALIZED)
173         FIXME("state = %x\n", state);
174
175     hres = IActiveScript_SetScriptState(script_host->script, SCRIPTSTATE_STARTED);
176     if(FAILED(hres)) {
177         WARN("Starting script failed: %08x\n", hres);
178         return FALSE;
179     }
180
181     hres = IActiveScript_AddNamedItem(script_host->script, windowW,
182             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS);
183     if(SUCCEEDED(hres)) {
184         V_VT(&var) = VT_BOOL;
185         V_BOOL(&var) = VARIANT_TRUE;
186         set_script_prop(script_host, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var);
187     }else {
188        WARN("AddNamedItem failed: %08x\n", hres);
189     }
190
191     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParseProcedure2,
192                                         (void**)&script_host->parse_proc);
193     if(FAILED(hres)) {
194         /* FIXME: QI for IActiveScriptParseProcedure */
195         WARN("Could not get IActiveScriptParseProcedure iface: %08x\n", hres);
196     }
197
198     return TRUE;
199 }
200
201 static void release_script_engine(ScriptHost *This)
202 {
203     if(!This->script)
204         return;
205
206     switch(This->script_state) {
207     case SCRIPTSTATE_CONNECTED:
208         IActiveScript_SetScriptState(This->script, SCRIPTSTATE_DISCONNECTED);
209
210     case SCRIPTSTATE_STARTED:
211     case SCRIPTSTATE_DISCONNECTED:
212     case SCRIPTSTATE_INITIALIZED:
213         IActiveScript_Close(This->script);
214
215     default:
216         if(This->parse_proc) {
217             IActiveScriptParseProcedure_Release(This->parse_proc);
218             This->parse_proc = NULL;
219         }
220
221         if(This->parse) {
222             IActiveScriptParse_Release(This->parse);
223             This->parse = NULL;
224         }
225     }
226
227     IActiveScript_Release(This->script);
228     This->script = NULL;
229     This->script_state = SCRIPTSTATE_UNINITIALIZED;
230 }
231
232 void connect_scripts(HTMLInnerWindow *window)
233 {
234     ScriptHost *iter;
235
236     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
237         if(iter->script_state == SCRIPTSTATE_STARTED)
238             IActiveScript_SetScriptState(iter->script, SCRIPTSTATE_CONNECTED);
239     }
240 }
241
242 static inline ScriptHost *impl_from_IActiveScriptSite(IActiveScriptSite *iface)
243 {
244     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSite_iface);
245 }
246
247 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
248 {
249     ScriptHost *This = impl_from_IActiveScriptSite(iface);
250
251     *ppv = NULL;
252
253     if(IsEqualGUID(&IID_IUnknown, riid)) {
254         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
255         *ppv = &This->IActiveScriptSite_iface;
256     }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) {
257         TRACE("(%p)->(IID_IActiveScriptSite %p)\n", This, ppv);
258         *ppv = &This->IActiveScriptSite_iface;
259     }else if(IsEqualGUID(&IID_IActiveScriptSiteInterruptPoll, riid)) {
260         TRACE("(%p)->(IID_IActiveScriptSiteInterruprtPoll %p)\n", This, ppv);
261         *ppv = &This->IActiveScriptSiteInterruptPoll_iface;
262     }else if(IsEqualGUID(&IID_IActiveScriptSiteWindow, riid)) {
263         TRACE("(%p)->(IID_IActiveScriptSiteWindow %p)\n", This, ppv);
264         *ppv = &This->IActiveScriptSiteWindow_iface;
265     }else if(IsEqualGUID(&IID_IActiveScriptSiteUIControl, riid)) {
266         TRACE("(%p)->(IID_IActiveScriptSiteUIControl %p)\n", This, ppv);
267         *ppv = &This->IActiveScriptSiteUIControl_iface;
268     }else if(IsEqualGUID(&IID_IActiveScriptSiteDebug, riid)) {
269         TRACE("(%p)->(IID_IActiveScriptSiteDebug %p)\n", This, ppv);
270         *ppv = &This->IActiveScriptSiteDebug_iface;
271     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
272         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
273         *ppv = &This->IServiceProvider_iface;
274     }else if(IsEqualGUID(&IID_ICanHandleException, riid)) {
275         TRACE("(%p)->(IID_ICanHandleException not supported %p)\n", This, ppv);
276         return E_NOINTERFACE;
277     }else {
278         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
279         return E_NOINTERFACE;
280     }
281
282     IUnknown_AddRef((IUnknown*)*ppv);
283     return S_OK;
284 }
285
286 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
287 {
288     ScriptHost *This = impl_from_IActiveScriptSite(iface);
289     LONG ref = InterlockedIncrement(&This->ref);
290
291     TRACE("(%p) ref=%d\n", This, ref);
292
293     return ref;
294 }
295
296 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
297 {
298     ScriptHost *This = impl_from_IActiveScriptSite(iface);
299     LONG ref = InterlockedDecrement(&This->ref);
300
301     TRACE("(%p) ref=%d\n", This, ref);
302
303     if(!ref) {
304         release_script_engine(This);
305         if(This->window)
306             list_remove(&This->entry);
307         heap_free(This);
308     }
309
310     return ref;
311 }
312
313 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid)
314 {
315     ScriptHost *This = impl_from_IActiveScriptSite(iface);
316
317     TRACE("(%p)->(%p)\n", This, plcid);
318
319     *plcid = GetUserDefaultLCID();
320     return S_OK;
321 }
322
323 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName,
324         DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti)
325 {
326     ScriptHost *This = impl_from_IActiveScriptSite(iface);
327
328     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_w(pstrName), dwReturnMask, ppiunkItem, ppti);
329
330     if(dwReturnMask != SCRIPTINFO_IUNKNOWN) {
331         FIXME("Unsupported mask %x\n", dwReturnMask);
332         return E_NOTIMPL;
333     }
334
335     *ppiunkItem = NULL;
336
337     if(strcmpW(pstrName, windowW))
338         return DISP_E_MEMBERNOTFOUND;
339
340     if(!This->window)
341         return E_FAIL;
342
343     /* FIXME: Return proxy object */
344     *ppiunkItem = (IUnknown*)&This->window->base.IHTMLWindow2_iface;
345     IUnknown_AddRef(*ppiunkItem);
346
347     return S_OK;
348 }
349
350 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion)
351 {
352     ScriptHost *This = impl_from_IActiveScriptSite(iface);
353     FIXME("(%p)->(%p)\n", This, pbstrVersion);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface,
358         const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo)
359 {
360     ScriptHost *This = impl_from_IActiveScriptSite(iface);
361     FIXME("(%p)->(%p %p)\n", This, pvarResult, pexcepinfo);
362     return E_NOTIMPL;
363 }
364
365 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState)
366 {
367     ScriptHost *This = impl_from_IActiveScriptSite(iface);
368
369     TRACE("(%p)->(%x)\n", This, ssScriptState);
370
371     This->script_state = ssScriptState;
372     return S_OK;
373 }
374
375 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror)
376 {
377     ScriptHost *This = impl_from_IActiveScriptSite(iface);
378     FIXME("(%p)->(%p)\n", This, pscripterror);
379     return E_NOTIMPL;
380 }
381
382 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
383 {
384     ScriptHost *This = impl_from_IActiveScriptSite(iface);
385
386     TRACE("(%p)->()\n", This);
387
388     return S_OK;
389 }
390
391 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
392 {
393     ScriptHost *This = impl_from_IActiveScriptSite(iface);
394
395     TRACE("(%p)->()\n", This);
396
397     return S_OK;
398 }
399
400 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
401     ActiveScriptSite_QueryInterface,
402     ActiveScriptSite_AddRef,
403     ActiveScriptSite_Release,
404     ActiveScriptSite_GetLCID,
405     ActiveScriptSite_GetItemInfo,
406     ActiveScriptSite_GetDocVersionString,
407     ActiveScriptSite_OnScriptTerminate,
408     ActiveScriptSite_OnStateChange,
409     ActiveScriptSite_OnScriptError,
410     ActiveScriptSite_OnEnterScript,
411     ActiveScriptSite_OnLeaveScript
412 };
413
414 static inline ScriptHost *impl_from_IActiveScriptSiteInterruptPoll(IActiveScriptSiteInterruptPoll *iface)
415 {
416     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteInterruptPoll_iface);
417 }
418
419 static HRESULT WINAPI ActiveScriptSiteInterruptPoll_QueryInterface(IActiveScriptSiteInterruptPoll *iface,
420         REFIID riid, void **ppv)
421 {
422     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
423     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
424 }
425
426 static ULONG WINAPI ActiveScriptSiteInterruptPoll_AddRef(IActiveScriptSiteInterruptPoll *iface)
427 {
428     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
429     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
430 }
431
432 static ULONG WINAPI ActiveScriptSiteInterruptPoll_Release(IActiveScriptSiteInterruptPoll *iface)
433 {
434     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
435     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
436 }
437
438 static HRESULT WINAPI ActiveScriptSiteInterruptPoll_QueryContinue(IActiveScriptSiteInterruptPoll *iface)
439 {
440     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
441
442     TRACE("(%p)\n", This);
443
444     return S_OK;
445 }
446
447 static const IActiveScriptSiteInterruptPollVtbl ActiveScriptSiteInterruptPollVtbl = {
448     ActiveScriptSiteInterruptPoll_QueryInterface,
449     ActiveScriptSiteInterruptPoll_AddRef,
450     ActiveScriptSiteInterruptPoll_Release,
451     ActiveScriptSiteInterruptPoll_QueryContinue
452 };
453
454 static inline ScriptHost *impl_from_IActiveScriptSiteWindow(IActiveScriptSiteWindow *iface)
455 {
456     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteWindow_iface);
457 }
458
459 static HRESULT WINAPI ActiveScriptSiteWindow_QueryInterface(IActiveScriptSiteWindow *iface,
460         REFIID riid, void **ppv)
461 {
462     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
463     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
464 }
465
466 static ULONG WINAPI ActiveScriptSiteWindow_AddRef(IActiveScriptSiteWindow *iface)
467 {
468     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
469     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
470 }
471
472 static ULONG WINAPI ActiveScriptSiteWindow_Release(IActiveScriptSiteWindow *iface)
473 {
474     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
475     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
476 }
477
478 static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *iface, HWND *phwnd)
479 {
480     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
481
482     TRACE("(%p)->(%p)\n", This, phwnd);
483
484     if(!This->window || !This->window->base.outer_window || !This->window->base.outer_window->doc_obj)
485         return E_UNEXPECTED;
486
487     *phwnd = This->window->base.outer_window->doc_obj->hwnd;
488     return S_OK;
489 }
490
491 static HRESULT WINAPI ActiveScriptSiteWindow_EnableModeless(IActiveScriptSiteWindow *iface, BOOL fEnable)
492 {
493     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
494     FIXME("(%p)->(%x)\n", This, fEnable);
495     return S_OK;
496 }
497
498 static const IActiveScriptSiteWindowVtbl ActiveScriptSiteWindowVtbl = {
499     ActiveScriptSiteWindow_QueryInterface,
500     ActiveScriptSiteWindow_AddRef,
501     ActiveScriptSiteWindow_Release,
502     ActiveScriptSiteWindow_GetWindow,
503     ActiveScriptSiteWindow_EnableModeless
504 };
505
506 static inline ScriptHost *impl_from_IActiveScriptSiteUIControl(IActiveScriptSiteUIControl *iface)
507 {
508     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteUIControl_iface);
509 }
510
511 static HRESULT WINAPI ActiveScriptSiteUIControl_QueryInterface(IActiveScriptSiteUIControl *iface, REFIID riid, void **ppv)
512 {
513     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
514     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
515 }
516
517 static ULONG WINAPI ActiveScriptSiteUIControl_AddRef(IActiveScriptSiteUIControl *iface)
518 {
519     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
520     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
521 }
522
523 static ULONG WINAPI ActiveScriptSiteUIControl_Release(IActiveScriptSiteUIControl *iface)
524 {
525     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
526     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
527 }
528
529 static HRESULT WINAPI ActiveScriptSiteUIControl_GetUIBehavior(IActiveScriptSiteUIControl *iface, SCRIPTUICITEM UicItem,
530         SCRIPTUICHANDLING *pUicHandling)
531 {
532     ScriptHost *This = impl_from_IActiveScriptSiteUIControl(iface);
533
534     WARN("(%p)->(%d %p) semi-stub\n", This, UicItem, pUicHandling);
535
536     *pUicHandling = SCRIPTUICHANDLING_ALLOW;
537     return S_OK;
538 }
539
540 static const IActiveScriptSiteUIControlVtbl ActiveScriptSiteUIControlVtbl = {
541     ActiveScriptSiteUIControl_QueryInterface,
542     ActiveScriptSiteUIControl_AddRef,
543     ActiveScriptSiteUIControl_Release,
544     ActiveScriptSiteUIControl_GetUIBehavior
545 };
546
547 static inline ScriptHost *impl_from_IActiveScriptSiteDebug(IActiveScriptSiteDebug *iface)
548 {
549     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteDebug_iface);
550 }
551
552 static HRESULT WINAPI ActiveScriptSiteDebug_QueryInterface(IActiveScriptSiteDebug *iface,
553         REFIID riid, void **ppv)
554 {
555     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
556     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
557 }
558
559 static ULONG WINAPI ActiveScriptSiteDebug_AddRef(IActiveScriptSiteDebug *iface)
560 {
561     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
562     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
563 }
564
565 static ULONG WINAPI ActiveScriptSiteDebug_Release(IActiveScriptSiteDebug *iface)
566 {
567     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
568     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
569 }
570
571 static HRESULT WINAPI ActiveScriptSiteDebug_GetDocumentContextFromPosition(IActiveScriptSiteDebug *iface,
572             CTXARG_T dwSourceContext, ULONG uCharacterOffset, ULONG uNumChars, IDebugDocumentContext **ppsc)
573 {
574     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
575     FIXME("(%p)->(%s %u %u %p)\n", This, wine_dbgstr_longlong(dwSourceContext), uCharacterOffset,
576           uNumChars, ppsc);
577     return E_NOTIMPL;
578 }
579
580 static HRESULT WINAPI ActiveScriptSiteDebug_GetApplication(IActiveScriptSiteDebug *iface, IDebugApplication **ppda)
581 {
582     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
583     FIXME("(%p)->(%p)\n", This, ppda);
584     return E_NOTIMPL;
585 }
586
587 static HRESULT WINAPI ActiveScriptSiteDebug_GetRootApplicationNode(IActiveScriptSiteDebug *iface,
588             IDebugApplicationNode **ppdanRoot)
589 {
590     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
591     FIXME("(%p)->(%p)\n", This, ppdanRoot);
592     return E_NOTIMPL;
593 }
594
595 static HRESULT WINAPI ActiveScriptSiteDebug_OnScriptErrorDebug(IActiveScriptSiteDebug *iface,
596             IActiveScriptErrorDebug *pErrorDebug, BOOL *pfEnterDebugger, BOOL *pfCallOnScriptErrorWhenContinuing)
597 {
598     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
599     FIXME("(%p)->(%p %p %p)\n", This, pErrorDebug, pfEnterDebugger, pfCallOnScriptErrorWhenContinuing);
600     return E_NOTIMPL;
601 }
602
603 static const IActiveScriptSiteDebugVtbl ActiveScriptSiteDebugVtbl = {
604     ActiveScriptSiteDebug_QueryInterface,
605     ActiveScriptSiteDebug_AddRef,
606     ActiveScriptSiteDebug_Release,
607     ActiveScriptSiteDebug_GetDocumentContextFromPosition,
608     ActiveScriptSiteDebug_GetApplication,
609     ActiveScriptSiteDebug_GetRootApplicationNode,
610     ActiveScriptSiteDebug_OnScriptErrorDebug
611 };
612
613 static inline ScriptHost *impl_from_IServiceProvider(IServiceProvider *iface)
614 {
615     return CONTAINING_RECORD(iface, ScriptHost, IServiceProvider_iface);
616 }
617
618 static HRESULT WINAPI ASServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
619 {
620     ScriptHost *This = impl_from_IServiceProvider(iface);
621     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
622 }
623
624 static ULONG WINAPI ASServiceProvider_AddRef(IServiceProvider *iface)
625 {
626     ScriptHost *This = impl_from_IServiceProvider(iface);
627     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
628 }
629
630 static ULONG WINAPI ASServiceProvider_Release(IServiceProvider *iface)
631 {
632     ScriptHost *This = impl_from_IServiceProvider(iface);
633     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
634 }
635
636 static HRESULT WINAPI ASServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
637         REFIID riid, void **ppv)
638 {
639     ScriptHost *This = impl_from_IServiceProvider(iface);
640
641     if(IsEqualGUID(&SID_SInternetHostSecurityManager, guidService)) {
642         TRACE("(%p)->(SID_SInternetHostSecurityManager)\n", This);
643
644         if(!This->window || !This->window->doc)
645             return E_NOINTERFACE;
646
647         return IInternetHostSecurityManager_QueryInterface(&This->window->doc->IInternetHostSecurityManager_iface,
648                 riid, ppv);
649     }
650
651     FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
652     return E_NOINTERFACE;
653 }
654
655 static const IServiceProviderVtbl ASServiceProviderVtbl = {
656     ASServiceProvider_QueryInterface,
657     ASServiceProvider_AddRef,
658     ASServiceProvider_Release,
659     ASServiceProvider_QueryService
660 };
661
662 static ScriptHost *create_script_host(HTMLInnerWindow *window, const GUID *guid)
663 {
664     ScriptHost *ret;
665     HRESULT hres;
666
667     ret = heap_alloc_zero(sizeof(*ret));
668     ret->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl;
669     ret->IActiveScriptSiteInterruptPoll_iface.lpVtbl = &ActiveScriptSiteInterruptPollVtbl;
670     ret->IActiveScriptSiteWindow_iface.lpVtbl = &ActiveScriptSiteWindowVtbl;
671     ret->IActiveScriptSiteUIControl_iface.lpVtbl = &ActiveScriptSiteUIControlVtbl;
672     ret->IActiveScriptSiteDebug_iface.lpVtbl = &ActiveScriptSiteDebugVtbl;
673     ret->IServiceProvider_iface.lpVtbl = &ASServiceProviderVtbl;
674     ret->ref = 1;
675     ret->window = window;
676     ret->script_state = SCRIPTSTATE_UNINITIALIZED;
677
678     ret->guid = *guid;
679     list_add_tail(&window->script_hosts, &ret->entry);
680
681     hres = CoCreateInstance(&ret->guid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
682             &IID_IActiveScript, (void**)&ret->script);
683     if(FAILED(hres))
684         WARN("Could not load script engine: %08x\n", hres);
685     else if(!init_script_engine(ret))
686         release_script_engine(ret);
687
688     return ret;
689 }
690
691 static void parse_text(ScriptHost *script_host, LPCWSTR text)
692 {
693     EXCEPINFO excepinfo;
694     VARIANT var;
695     HRESULT hres;
696
697     TRACE("%s\n", debugstr_w(text));
698
699     VariantInit(&var);
700     memset(&excepinfo, 0, sizeof(excepinfo));
701     TRACE(">>>\n");
702     hres = IActiveScriptParse_ParseScriptText(script_host->parse, text, windowW, NULL, script_endW,
703                                               0, 0, SCRIPTTEXT_ISVISIBLE|SCRIPTTEXT_HOSTMANAGESSOURCE,
704                                               &var, &excepinfo);
705     if(SUCCEEDED(hres))
706         TRACE("<<<\n");
707     else
708         WARN("<<< %08x\n", hres);
709
710 }
711
712 static void parse_extern_script(ScriptHost *script_host, LPCWSTR src)
713 {
714     IMoniker *mon;
715     WCHAR *text;
716     HRESULT hres;
717
718     static const WCHAR wine_schemaW[] = {'w','i','n','e',':'};
719
720     if(strlenW(src) > sizeof(wine_schemaW)/sizeof(WCHAR) && !memcmp(src, wine_schemaW, sizeof(wine_schemaW)))
721         src += sizeof(wine_schemaW)/sizeof(WCHAR);
722
723     hres = CreateURLMoniker(NULL, src, &mon);
724     if(FAILED(hres))
725         return;
726
727     hres = bind_mon_to_wstr(script_host->window, mon, &text);
728     IMoniker_Release(mon);
729     if(FAILED(hres))
730         return;
731
732     parse_text(script_host, text);
733
734     heap_free(text);
735 }
736
737 static void parse_inline_script(ScriptHost *script_host, HTMLScriptElement *script_elem)
738 {
739     const PRUnichar *text;
740     nsAString text_str;
741     nsresult nsres;
742
743     nsAString_Init(&text_str, NULL);
744     nsres = nsIDOMHTMLScriptElement_GetText(script_elem->nsscript, &text_str);
745     nsAString_GetData(&text_str, &text);
746
747     if(NS_FAILED(nsres)) {
748         ERR("GetText failed: %08x\n", nsres);
749     }else if(*text) {
750         script_elem->parsed = TRUE;
751         parse_text(script_host, text);
752     }
753
754     nsAString_Finish(&text_str);
755 }
756
757 static void parse_script_elem(ScriptHost *script_host, HTMLScriptElement *script_elem)
758 {
759     nsAString src_str, event_str;
760     const PRUnichar *src;
761     nsresult nsres;
762
763     nsAString_Init(&event_str, NULL);
764     nsres = nsIDOMHTMLScriptElement_GetEvent(script_elem->nsscript, &event_str);
765     if(NS_SUCCEEDED(nsres)) {
766         const PRUnichar *event;
767
768         nsAString_GetData(&event_str, &event);
769         if(*event) {
770             TRACE("deferring event %s script evaluation\n", debugstr_w(event));
771             nsAString_Finish(&event_str);
772             return;
773         }
774     }else {
775         ERR("GetAttribute(event) failed: %08x\n", nsres);
776     }
777     nsAString_Finish(&event_str);
778
779     nsAString_Init(&src_str, NULL);
780     nsres = nsIDOMHTMLScriptElement_GetSrc(script_elem->nsscript, &src_str);
781     nsAString_GetData(&src_str, &src);
782
783     if(NS_FAILED(nsres)) {
784         ERR("GetSrc failed: %08x\n", nsres);
785     }else if(*src) {
786         script_elem->parsed = TRUE;
787         parse_extern_script(script_host, src);
788     }else {
789         parse_inline_script(script_host, script_elem);
790     }
791
792     nsAString_Finish(&src_str);
793 }
794
795 static GUID get_default_script_guid(HTMLInnerWindow *window)
796 {
797     /* If not specified, we should use very first script host that was created for the page (or JScript if none) */
798     return list_empty(&window->script_hosts)
799         ? CLSID_JScript
800         : LIST_ENTRY(list_head(&window->script_hosts), ScriptHost, entry)->guid;
801 }
802
803 static BOOL get_guid_from_type(LPCWSTR type, GUID *guid)
804 {
805     const WCHAR text_javascriptW[] =
806         {'t','e','x','t','/','j','a','v','a','s','c','r','i','p','t',0};
807     const WCHAR text_vbscriptW[] =
808         {'t','e','x','t','/','v','b','s','c','r','i','p','t',0};
809
810     /* FIXME: Handle more types */
811     if(!strcmpiW(type, text_javascriptW)) {
812         *guid = CLSID_JScript;
813     }else if(!strcmpiW(type, text_vbscriptW)) {
814         *guid = CLSID_VBScript;
815     }else {
816         FIXME("Unknown type %s\n", debugstr_w(type));
817         return FALSE;
818     }
819
820     return TRUE;
821 }
822
823 static BOOL get_guid_from_language(LPCWSTR type, GUID *guid)
824 {
825     HRESULT hres;
826
827     hres = CLSIDFromProgID(type, guid);
828     if(FAILED(hres))
829         return FALSE;
830
831     /* FIXME: Check CATID_ActiveScriptParse */
832
833     return TRUE;
834 }
835
836 static BOOL get_script_guid(HTMLInnerWindow *window, nsIDOMHTMLScriptElement *nsscript, GUID *guid)
837 {
838     nsAString attr_str, val_str;
839     BOOL ret = FALSE;
840     nsresult nsres;
841
842     static const PRUnichar languageW[] = {'l','a','n','g','u','a','g','e',0};
843
844     nsAString_Init(&val_str, NULL);
845
846     nsres = nsIDOMHTMLScriptElement_GetType(nsscript, &val_str);
847     if(NS_SUCCEEDED(nsres)) {
848         const PRUnichar *type;
849
850         nsAString_GetData(&val_str, &type);
851         if(*type) {
852             ret = get_guid_from_type(type, guid);
853             nsAString_Finish(&val_str);
854             return ret;
855         }
856     }else {
857         ERR("GetType failed: %08x\n", nsres);
858     }
859
860     nsAString_InitDepend(&attr_str, languageW);
861     nsres = nsIDOMHTMLScriptElement_GetAttribute(nsscript, &attr_str, &val_str);
862     nsAString_Finish(&attr_str);
863     if(NS_SUCCEEDED(nsres)) {
864         const PRUnichar *language;
865
866         nsAString_GetData(&val_str, &language);
867
868         if(*language) {
869             ret = get_guid_from_language(language, guid);
870         }else {
871             *guid = get_default_script_guid(window);
872             ret = TRUE;
873         }
874     }else {
875         ERR("GetAttribute(language) failed: %08x\n", nsres);
876     }
877
878     nsAString_Finish(&val_str);
879
880     return ret;
881 }
882
883 static ScriptHost *get_script_host(HTMLInnerWindow *window, const GUID *guid)
884 {
885     ScriptHost *iter;
886
887     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
888         if(IsEqualGUID(guid, &iter->guid))
889             return iter;
890     }
891
892     return create_script_host(window, guid);
893 }
894
895 static ScriptHost *get_elem_script_host(HTMLInnerWindow *window, HTMLScriptElement *script_elem)
896 {
897     GUID guid;
898
899     if(!get_script_guid(window, script_elem->nsscript, &guid)) {
900         WARN("Could not find script GUID\n");
901         return NULL;
902     }
903
904     if(IsEqualGUID(&CLSID_JScript, &guid)
905        && (!window->base.outer_window || window->base.outer_window->scriptmode != SCRIPTMODE_ACTIVESCRIPT)) {
906         TRACE("Ignoring JScript\n");
907         return NULL;
908     }
909
910     return get_script_host(window, &guid);
911 }
912
913 void doc_insert_script(HTMLInnerWindow *window, HTMLScriptElement *script_elem)
914 {
915     ScriptHost *script_host;
916
917     script_host = get_elem_script_host(window, script_elem);
918     if(!script_host)
919         return;
920
921     if(script_host->parse)
922         parse_script_elem(script_host, script_elem);
923 }
924
925 IDispatch *script_parse_event(HTMLInnerWindow *window, LPCWSTR text)
926 {
927     ScriptHost *script_host;
928     GUID guid;
929     const WCHAR *ptr;
930     IDispatch *disp;
931     HRESULT hres;
932
933     static const WCHAR delimiterW[] = {'\"',0};
934
935     TRACE("%s\n", debugstr_w(text));
936
937     for(ptr = text; isalnumW(*ptr); ptr++);
938     if(*ptr == ':') {
939         LPWSTR language;
940         BOOL b;
941
942         language = heap_alloc((ptr-text+1)*sizeof(WCHAR));
943         memcpy(language, text, (ptr-text)*sizeof(WCHAR));
944         language[ptr-text] = 0;
945
946         b = get_guid_from_language(language, &guid);
947
948         heap_free(language);
949
950         if(!b) {
951             WARN("Could not find language\n");
952             return NULL;
953         }
954
955         ptr++;
956     }else {
957         ptr = text;
958         guid = get_default_script_guid(window);
959     }
960
961     if(IsEqualGUID(&CLSID_JScript, &guid)
962        && (!window->base.outer_window || window->base.outer_window->scriptmode != SCRIPTMODE_ACTIVESCRIPT)) {
963         TRACE("Ignoring JScript\n");
964         return NULL;
965     }
966
967     script_host = get_script_host(window, &guid);
968     if(!script_host || !script_host->parse_proc)
969         return NULL;
970
971     hres = IActiveScriptParseProcedure_ParseProcedureText(script_host->parse_proc, ptr, NULL, emptyW,
972             NULL, NULL, delimiterW, 0 /* FIXME */, 0,
973             SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp);
974     if(FAILED(hres)) {
975         WARN("ParseProcedureText failed: %08x\n", hres);
976         return NULL;
977     }
978
979     TRACE("ret %p\n", disp);
980     return disp;
981 }
982
983 HRESULT exec_script(HTMLInnerWindow *window, const WCHAR *code, const WCHAR *lang, VARIANT *ret)
984 {
985     ScriptHost *script_host;
986     EXCEPINFO ei;
987     GUID guid;
988     HRESULT hres;
989
990     static const WCHAR delimW[] = {'"',0};
991
992     if(!get_guid_from_language(lang, &guid)) {
993         WARN("Could not find script GUID\n");
994         return CO_E_CLASSSTRING;
995     }
996
997     script_host = get_script_host(window, &guid);
998     if(!script_host) {
999         FIXME("No script host\n");
1000         return E_FAIL;
1001     }
1002
1003     if(!script_host->parse) {
1004         FIXME("script_host->parse == NULL\n");
1005         return E_FAIL;
1006     }
1007
1008     memset(&ei, 0, sizeof(ei));
1009     TRACE(">>>\n");
1010     hres = IActiveScriptParse_ParseScriptText(script_host->parse, code, NULL, NULL, delimW, 0, 0, SCRIPTTEXT_ISVISIBLE, ret, &ei);
1011     if(SUCCEEDED(hres))
1012         TRACE("<<<\n");
1013     else
1014         WARN("<<< %08x\n", hres);
1015
1016     return hres;
1017 }
1018
1019 IDispatch *get_script_disp(ScriptHost *script_host)
1020 {
1021     IDispatch *disp;
1022     HRESULT hres;
1023
1024     if(!script_host->script)
1025         return NULL;
1026
1027     hres = IActiveScript_GetScriptDispatch(script_host->script, windowW, &disp);
1028     if(FAILED(hres))
1029         return NULL;
1030
1031     return disp;
1032 }
1033
1034 static HTMLElement *find_event_target(HTMLDocumentNode *doc, HTMLScriptElement *script_elem)
1035 {
1036     const PRUnichar *target_id;
1037     nsAString target_id_str;
1038     HTMLElement *elem;
1039     nsresult nsres;
1040     HRESULT hres;
1041
1042     nsAString_Init(&target_id_str, NULL);
1043     nsres = nsIDOMHTMLScriptElement_GetHtmlFor(script_elem->nsscript, &target_id_str);
1044     if(NS_FAILED(nsres)) {
1045         ERR("GetScriptFor failed: %08x\n", nsres);
1046         nsAString_Finish(&target_id_str);
1047         return NULL;
1048     }
1049
1050     nsAString_GetData(&target_id_str, &target_id);
1051     if(!*target_id || !strcmpW(target_id, documentW) || !strcmpW(target_id, windowW)) {
1052         FIXME("for %s not supported\n", debugstr_w(target_id));
1053         elem = NULL;
1054     }else {
1055         hres = get_doc_elem_by_id(doc, target_id, &elem);
1056         if(FAILED(hres))
1057             elem = NULL;
1058     }
1059     nsAString_Finish(&target_id_str);
1060
1061     return elem;
1062 }
1063
1064 static BOOL parse_event_str(WCHAR *event, const WCHAR **args)
1065 {
1066     WCHAR *ptr;
1067
1068     for(ptr = event; isalnumW(*ptr); ptr++);
1069     if(!*ptr) {
1070         *args = NULL;
1071         return TRUE;
1072     }
1073
1074     if(*ptr != '(')
1075         return FALSE;
1076
1077     *ptr++ = 0;
1078     *args = ptr;
1079     while(isalnumW(*ptr) || isspaceW(*ptr) || *ptr == ',')
1080         ptr++;
1081
1082     if(*ptr++ != ')')
1083         return FALSE;
1084     *ptr++ = 0;
1085     return !*ptr;
1086 }
1087
1088 static IDispatch *parse_event_elem(HTMLDocumentNode *doc, HTMLScriptElement *script_elem, WCHAR **ret_event)
1089 {
1090     ScriptHost *script_host;
1091     WCHAR *event = NULL;
1092     const WCHAR *args;
1093     nsAString nsstr;
1094     IDispatch *disp;
1095     nsresult nsres;
1096     HRESULT hres;
1097
1098     if(script_elem->parsed)
1099         return NULL;
1100
1101     script_host = get_elem_script_host(doc->window, script_elem);
1102     if(!script_host || !script_host->parse_proc)
1103         return NULL;
1104
1105     nsAString_Init(&nsstr, NULL);
1106     nsres = nsIDOMHTMLScriptElement_GetEvent(script_elem->nsscript, &nsstr);
1107     if(NS_SUCCEEDED(nsres)) {
1108         const PRUnichar *event_val;
1109
1110         nsAString_GetData(&nsstr, &event_val);
1111         event = heap_strdupW(event_val);
1112     }
1113     nsAString_Finish(&nsstr);
1114     if(!event)
1115         return NULL;
1116
1117     if(!parse_event_str(event, &args)) {
1118         WARN("parsing %s failed\n", debugstr_w(event));
1119         heap_free(event);
1120         return NULL;
1121     }
1122
1123     nsAString_Init(&nsstr, NULL);
1124     nsres = nsIDOMHTMLScriptElement_GetText(script_elem->nsscript, &nsstr);
1125     if(NS_SUCCEEDED(nsres)) {
1126         const PRUnichar *text;
1127
1128         nsAString_GetData(&nsstr, &text);
1129         hres = IActiveScriptParseProcedure_ParseProcedureText(script_host->parse_proc, text, args,
1130                 emptyW, NULL, NULL, script_endW, 0, 0,
1131                 SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp);
1132         if(FAILED(hres))
1133             disp = NULL;
1134     }else {
1135         ERR("GetText failed: %08x\n", nsres);
1136         disp = NULL;
1137     }
1138     nsAString_Finish(&nsstr);
1139     if(!disp) {
1140         heap_free(event);
1141         return NULL;
1142     }
1143
1144     *ret_event = event;
1145     return disp;
1146 }
1147
1148 void bind_event_scripts(HTMLDocumentNode *doc)
1149 {
1150     HTMLPluginContainer *plugin_container;
1151     nsIDOMHTMLScriptElement *nsscript;
1152     HTMLScriptElement *script_elem;
1153     HTMLElement *event_target;
1154     nsIDOMNodeList *node_list;
1155     nsIDOMNode *script_node;
1156     nsAString selector_str;
1157     IDispatch *event_disp;
1158     PRUint32 length, i;
1159     WCHAR *event;
1160     nsresult nsres;
1161     HRESULT hres;
1162
1163     static const PRUnichar selectorW[] = {'s','c','r','i','p','t','[','e','v','e','n','t',']',0};
1164
1165     TRACE("%p\n", doc);
1166
1167     if(!doc->nsdoc)
1168         return;
1169
1170     nsAString_InitDepend(&selector_str, selectorW);
1171     nsres = nsIDOMNodeSelector_QuerySelectorAll(doc->nsnode_selector, &selector_str, &node_list);
1172     nsAString_Finish(&selector_str);
1173     if(NS_FAILED(nsres)) {
1174         ERR("QuerySelectorAll failed: %08x\n", nsres);
1175         return;
1176     }
1177
1178     if(!node_list)
1179         return;
1180
1181     nsres = nsIDOMNodeList_GetLength(node_list, &length);
1182     assert(nsres == NS_OK);
1183
1184     for(i=0; i < length; i++) {
1185         nsres = nsIDOMNodeList_Item(node_list, i, &script_node);
1186         if(NS_FAILED(nsres) || !script_node) {
1187             ERR("Item(%d) failed: %08x\n", i, nsres);
1188             continue;
1189         }
1190
1191         nsres = nsIDOMNode_QueryInterface(script_node, &IID_nsIDOMHTMLScriptElement, (void**)&nsscript);
1192         assert(nsres == NS_OK);
1193         nsIDOMNode_Release(script_node);
1194
1195         hres = script_elem_from_nsscript(doc, nsscript, &script_elem);
1196         if(FAILED(hres))
1197             continue;
1198
1199         event_disp = parse_event_elem(doc, script_elem, &event);
1200         if(event_disp) {
1201             event_target = find_event_target(doc, script_elem);
1202             if(event_target) {
1203                 IHTMLElement_QueryInterface(&event_target->IHTMLElement_iface, &IID_HTMLPluginContainer, (void**)&plugin_container);
1204
1205                 if(plugin_container)
1206                     FIXME("ActiveX events not supported\n");
1207                 else
1208                     bind_elem_event(doc, event_target, event, event_disp);
1209
1210                 IHTMLElement_Release(&event_target->IHTMLElement_iface);
1211             }
1212
1213             heap_free(event);
1214             IDispatch_Release(event_disp);
1215         }
1216
1217         IHTMLScriptElement_Release(&script_elem->IHTMLScriptElement_iface);
1218     }
1219
1220     nsIDOMNodeList_Release(node_list);
1221 }
1222
1223 BOOL find_global_prop(HTMLInnerWindow *window, BSTR name, DWORD flags, ScriptHost **ret_host, DISPID *ret_id)
1224 {
1225     IDispatchEx *dispex;
1226     IDispatch *disp;
1227     ScriptHost *iter;
1228     HRESULT hres;
1229
1230     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
1231         disp = get_script_disp(iter);
1232         if(!disp)
1233             continue;
1234
1235         hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
1236         if(SUCCEEDED(hres)) {
1237             hres = IDispatchEx_GetDispID(dispex, name, flags & (~fdexNameEnsure), ret_id);
1238             IDispatchEx_Release(dispex);
1239         }else {
1240             FIXME("No IDispatchEx\n");
1241             hres = E_NOTIMPL;
1242         }
1243
1244         IDispatch_Release(disp);
1245         if(SUCCEEDED(hres)) {
1246             *ret_host = iter;
1247             return TRUE;
1248         }
1249     }
1250
1251     return FALSE;
1252 }
1253
1254 static BOOL is_jscript_available(void)
1255 {
1256     static BOOL available, checked;
1257
1258     if(!checked) {
1259         IUnknown *unk;
1260         HRESULT hres = CoGetClassObject(&CLSID_JScript, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
1261
1262         if(SUCCEEDED(hres)) {
1263             available = TRUE;
1264             IUnknown_Release(unk);
1265         }else {
1266             available = FALSE;
1267         }
1268         checked = TRUE;
1269     }
1270
1271     return available;
1272 }
1273
1274 void set_script_mode(HTMLOuterWindow *window, SCRIPTMODE mode)
1275 {
1276     nsIWebBrowserSetup *setup;
1277     nsresult nsres;
1278
1279     if(mode == SCRIPTMODE_ACTIVESCRIPT && !is_jscript_available()) {
1280         TRACE("jscript.dll not available\n");
1281         window->scriptmode = SCRIPTMODE_GECKO;
1282         return;
1283     }
1284
1285     window->scriptmode = mode;
1286
1287     if(!window->doc_obj->nscontainer || !window->doc_obj->nscontainer->webbrowser)
1288         return;
1289
1290     nsres = nsIWebBrowser_QueryInterface(window->doc_obj->nscontainer->webbrowser,
1291             &IID_nsIWebBrowserSetup, (void**)&setup);
1292     if(NS_SUCCEEDED(nsres)) {
1293         nsres = nsIWebBrowserSetup_SetProperty(setup, SETUP_ALLOW_JAVASCRIPT,
1294                 window->scriptmode == SCRIPTMODE_GECKO);
1295         nsIWebBrowserSetup_Release(setup);
1296     }
1297
1298     if(NS_FAILED(nsres))
1299         ERR("JavaScript setup failed: %08x\n", nsres);
1300 }
1301
1302 void release_script_hosts(HTMLInnerWindow *window)
1303 {
1304     ScriptHost *iter;
1305
1306     while(!list_empty(&window->script_hosts)) {
1307         iter = LIST_ENTRY(list_head(&window->script_hosts), ScriptHost, entry);
1308
1309         release_script_engine(iter);
1310         list_remove(&iter->entry);
1311         iter->window = NULL;
1312         IActiveScriptSite_Release(&iter->IActiveScriptSite_iface);
1313     }
1314 }