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