wined3d: Remove unneeded address-of operators from function names.
[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
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29 #include "activscp.h"
30 #include "activdbg.h"
31
32 #include "wine/debug.h"
33
34 #include "mshtml_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 #ifdef _WIN64
39 #define CTXARG_T DWORDLONG
40 #define IActiveScriptSiteDebugVtbl IActiveScriptSiteDebug64Vtbl
41 #else
42 #define CTXARG_T DWORD
43 #define IActiveScriptSiteDebugVtbl IActiveScriptSiteDebug32Vtbl
44 #endif
45
46 static const WCHAR windowW[] = {'w','i','n','d','o','w',0};
47 static const WCHAR emptyW[] = {0};
48
49 static const CLSID CLSID_JScript =
50     {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}};
51
52 struct ScriptHost {
53     IActiveScriptSite              IActiveScriptSite_iface;
54     IActiveScriptSiteInterruptPoll IActiveScriptSiteInterruptPoll_iface;
55     IActiveScriptSiteWindow        IActiveScriptSiteWindow_iface;
56     IActiveScriptSiteDebug         IActiveScriptSiteDebug_iface;
57     IServiceProvider               IServiceProvider_iface;
58
59     LONG ref;
60
61     IActiveScript *script;
62     IActiveScriptParse *parse;
63     IActiveScriptParseProcedure *parse_proc;
64
65     SCRIPTSTATE script_state;
66
67     HTMLWindow *window;
68
69     GUID guid;
70     struct list entry;
71 };
72
73 static void set_script_prop(ScriptHost *script_host, DWORD property, VARIANT *val)
74 {
75     IActiveScriptProperty *script_prop;
76     HRESULT hres;
77
78     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptProperty,
79             (void**)&script_prop);
80     if(FAILED(hres)) {
81         WARN("Could not get IActiveScriptProperty iface: %08x\n", hres);
82         return;
83     }
84
85     hres = IActiveScriptProperty_SetProperty(script_prop, property, NULL, val);
86     IActiveScriptProperty_Release(script_prop);
87     if(FAILED(hres))
88         WARN("SetProperty(%x) failed: %08x\n", property, hres);
89 }
90
91 static BOOL init_script_engine(ScriptHost *script_host)
92 {
93     IObjectSafety *safety;
94     SCRIPTSTATE state;
95     DWORD supported_opts=0, enabled_opts=0;
96     VARIANT var;
97     HRESULT hres;
98
99     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParse, (void**)&script_host->parse);
100     if(FAILED(hres)) {
101         WARN("Could not get IActiveScriptHost: %08x\n", hres);
102         return FALSE;
103     }
104
105     hres = IActiveScript_QueryInterface(script_host->script, &IID_IObjectSafety, (void**)&safety);
106     if(FAILED(hres)) {
107         FIXME("Could not get IObjectSafety: %08x\n", hres);
108         return FALSE;
109     }
110
111     hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported_opts, &enabled_opts);
112     if(FAILED(hres)) {
113         FIXME("GetInterfaceSafetyOptions failed: %08x\n", hres);
114     }else if(!(supported_opts & INTERFACE_USES_DISPEX)) {
115         FIXME("INTERFACE_USES_DISPEX is not supported\n");
116     }else {
117         hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse,
118                 INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER,
119                 INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER);
120         if(FAILED(hres))
121             FIXME("SetInterfaceSafetyOptions failed: %08x\n", hres);
122     }
123
124     IObjectSafety_Release(safety);
125     if(FAILED(hres))
126         return FALSE;
127
128     V_VT(&var) = VT_I4;
129     V_I4(&var) = 1;
130     set_script_prop(script_host, SCRIPTPROP_INVOKEVERSIONING, &var);
131
132     V_VT(&var) = VT_BOOL;
133     V_BOOL(&var) = VARIANT_TRUE;
134     set_script_prop(script_host, SCRIPTPROP_HACK_TRIDENTEVENTSINK, &var);
135
136     hres = IActiveScriptParse64_InitNew(script_host->parse);
137     if(FAILED(hres)) {
138         WARN("InitNew failed: %08x\n", hres);
139         return FALSE;
140     }
141
142     hres = IActiveScript_SetScriptSite(script_host->script, &script_host->IActiveScriptSite_iface);
143     if(FAILED(hres)) {
144         WARN("SetScriptSite failed: %08x\n", hres);
145         IActiveScript_Close(script_host->script);
146         return FALSE;
147     }
148
149     hres = IActiveScript_GetScriptState(script_host->script, &state);
150     if(FAILED(hres))
151         WARN("GetScriptState failed: %08x\n", hres);
152     else if(state != SCRIPTSTATE_INITIALIZED)
153         FIXME("state = %x\n", state);
154
155     hres = IActiveScript_SetScriptState(script_host->script, SCRIPTSTATE_STARTED);
156     if(FAILED(hres)) {
157         WARN("Starting script failed: %08x\n", hres);
158         return FALSE;
159     }
160
161     hres = IActiveScript_AddNamedItem(script_host->script, windowW,
162             SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS);
163     if(SUCCEEDED(hres)) {
164         V_VT(&var) = VT_BOOL;
165         V_BOOL(&var) = VARIANT_TRUE;
166         set_script_prop(script_host, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var);
167     }else {
168        WARN("AddNamedItem failed: %08x\n", hres);
169     }
170
171     hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParseProcedure2,
172                                         (void**)&script_host->parse_proc);
173     if(FAILED(hres)) {
174         /* FIXME: QI for IActiveScriptParseProcedure */
175         WARN("Could not get IActiveScriptParseProcedure iface: %08x\n", hres);
176     }
177
178     return TRUE;
179 }
180
181 static void release_script_engine(ScriptHost *This)
182 {
183     if(!This->script)
184         return;
185
186     switch(This->script_state) {
187     case SCRIPTSTATE_CONNECTED:
188         IActiveScript_SetScriptState(This->script, SCRIPTSTATE_DISCONNECTED);
189
190     case SCRIPTSTATE_STARTED:
191     case SCRIPTSTATE_DISCONNECTED:
192     case SCRIPTSTATE_INITIALIZED:
193         IActiveScript_Close(This->script);
194
195     default:
196         if(This->parse_proc) {
197             IUnknown_Release(This->parse_proc);
198             This->parse_proc = NULL;
199         }
200
201         if(This->parse) {
202             IUnknown_Release(This->parse);
203             This->parse = NULL;
204         }
205     }
206
207     IActiveScript_Release(This->script);
208     This->script = NULL;
209     This->script_state = SCRIPTSTATE_UNINITIALIZED;
210 }
211
212 void connect_scripts(HTMLWindow *window)
213 {
214     ScriptHost *iter;
215
216     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
217         if(iter->script_state == SCRIPTSTATE_STARTED)
218             IActiveScript_SetScriptState(iter->script, SCRIPTSTATE_CONNECTED);
219     }
220 }
221
222 static inline ScriptHost *impl_from_IActiveScriptSite(IActiveScriptSite *iface)
223 {
224     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSite_iface);
225 }
226
227 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
228 {
229     ScriptHost *This = impl_from_IActiveScriptSite(iface);
230
231     *ppv = NULL;
232
233     if(IsEqualGUID(&IID_IUnknown, riid)) {
234         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
235         *ppv = &This->IActiveScriptSite_iface;
236     }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) {
237         TRACE("(%p)->(IID_IActiveScriptSite %p)\n", This, ppv);
238         *ppv = &This->IActiveScriptSite_iface;
239     }else if(IsEqualGUID(&IID_IActiveScriptSiteInterruptPoll, riid)) {
240         TRACE("(%p)->(IID_IActiveScriptSiteInterruprtPoll %p)\n", This, ppv);
241         *ppv = &This->IActiveScriptSiteInterruptPoll_iface;
242     }else if(IsEqualGUID(&IID_IActiveScriptSiteWindow, riid)) {
243         TRACE("(%p)->(IID_IActiveScriptSiteWindow %p)\n", This, ppv);
244         *ppv = &This->IActiveScriptSiteWindow_iface;
245     }else if(IsEqualGUID(&IID_IActiveScriptSiteDebug, riid)) {
246         TRACE("(%p)->(IID_IActiveScriptSiteDebug %p)\n", This, ppv);
247         *ppv = &This->IActiveScriptSiteDebug_iface;
248     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
249         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
250         *ppv = &This->IServiceProvider_iface;
251     }else if(IsEqualGUID(&IID_ICanHandleException, riid)) {
252         TRACE("(%p)->(IID_ICanHandleException not supported %p)\n", This, ppv);
253         return E_NOINTERFACE;
254     }else {
255         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
256         return E_NOINTERFACE;
257     }
258
259     IUnknown_AddRef((IUnknown*)*ppv);
260     return S_OK;
261 }
262
263 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
264 {
265     ScriptHost *This = impl_from_IActiveScriptSite(iface);
266     LONG ref = InterlockedIncrement(&This->ref);
267
268     TRACE("(%p) ref=%d\n", This, ref);
269
270     return ref;
271 }
272
273 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
274 {
275     ScriptHost *This = impl_from_IActiveScriptSite(iface);
276     LONG ref = InterlockedDecrement(&This->ref);
277
278     TRACE("(%p) ref=%d\n", This, ref);
279
280     if(!ref) {
281         release_script_engine(This);
282         if(This->window)
283             list_remove(&This->entry);
284         heap_free(This);
285     }
286
287     return ref;
288 }
289
290 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid)
291 {
292     ScriptHost *This = impl_from_IActiveScriptSite(iface);
293
294     TRACE("(%p)->(%p)\n", This, plcid);
295
296     *plcid = GetUserDefaultLCID();
297     return S_OK;
298 }
299
300 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName,
301         DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti)
302 {
303     ScriptHost *This = impl_from_IActiveScriptSite(iface);
304
305     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_w(pstrName), dwReturnMask, ppiunkItem, ppti);
306
307     if(dwReturnMask != SCRIPTINFO_IUNKNOWN) {
308         FIXME("Unsupported mask %x\n", dwReturnMask);
309         return E_NOTIMPL;
310     }
311
312     *ppiunkItem = NULL;
313
314     if(strcmpW(pstrName, windowW))
315         return DISP_E_MEMBERNOTFOUND;
316
317     if(!This->window)
318         return E_FAIL;
319
320     /* FIXME: Return proxy object */
321     *ppiunkItem = (IUnknown*)&This->window->IHTMLWindow2_iface;
322     IUnknown_AddRef(*ppiunkItem);
323
324     return S_OK;
325 }
326
327 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion)
328 {
329     ScriptHost *This = impl_from_IActiveScriptSite(iface);
330     FIXME("(%p)->(%p)\n", This, pbstrVersion);
331     return E_NOTIMPL;
332 }
333
334 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface,
335         const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo)
336 {
337     ScriptHost *This = impl_from_IActiveScriptSite(iface);
338     FIXME("(%p)->(%p %p)\n", This, pvarResult, pexcepinfo);
339     return E_NOTIMPL;
340 }
341
342 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState)
343 {
344     ScriptHost *This = impl_from_IActiveScriptSite(iface);
345
346     TRACE("(%p)->(%x)\n", This, ssScriptState);
347
348     This->script_state = ssScriptState;
349     return S_OK;
350 }
351
352 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror)
353 {
354     ScriptHost *This = impl_from_IActiveScriptSite(iface);
355     FIXME("(%p)->(%p)\n", This, pscripterror);
356     return E_NOTIMPL;
357 }
358
359 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
360 {
361     ScriptHost *This = impl_from_IActiveScriptSite(iface);
362
363     TRACE("(%p)->()\n", This);
364
365     return S_OK;
366 }
367
368 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
369 {
370     ScriptHost *This = impl_from_IActiveScriptSite(iface);
371
372     TRACE("(%p)->()\n", This);
373
374     return S_OK;
375 }
376
377 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
378     ActiveScriptSite_QueryInterface,
379     ActiveScriptSite_AddRef,
380     ActiveScriptSite_Release,
381     ActiveScriptSite_GetLCID,
382     ActiveScriptSite_GetItemInfo,
383     ActiveScriptSite_GetDocVersionString,
384     ActiveScriptSite_OnScriptTerminate,
385     ActiveScriptSite_OnStateChange,
386     ActiveScriptSite_OnScriptError,
387     ActiveScriptSite_OnEnterScript,
388     ActiveScriptSite_OnLeaveScript
389 };
390
391 static inline ScriptHost *impl_from_IActiveScriptSiteInterruptPoll(IActiveScriptSiteInterruptPoll *iface)
392 {
393     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteInterruptPoll_iface);
394 }
395
396 static HRESULT WINAPI ActiveScriptSiteInterruptPoll_QueryInterface(IActiveScriptSiteInterruptPoll *iface,
397         REFIID riid, void **ppv)
398 {
399     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
400     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
401 }
402
403 static ULONG WINAPI ActiveScriptSiteInterruptPoll_AddRef(IActiveScriptSiteInterruptPoll *iface)
404 {
405     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
406     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
407 }
408
409 static ULONG WINAPI ActiveScriptSiteInterruptPoll_Release(IActiveScriptSiteInterruptPoll *iface)
410 {
411     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
412     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
413 }
414
415 static HRESULT WINAPI ActiveScriptSiteInterruptPoll_QueryContinue(IActiveScriptSiteInterruptPoll *iface)
416 {
417     ScriptHost *This = impl_from_IActiveScriptSiteInterruptPoll(iface);
418
419     TRACE("(%p)\n", This);
420
421     return S_OK;
422 }
423
424 static const IActiveScriptSiteInterruptPollVtbl ActiveScriptSiteInterruptPollVtbl = {
425     ActiveScriptSiteInterruptPoll_QueryInterface,
426     ActiveScriptSiteInterruptPoll_AddRef,
427     ActiveScriptSiteInterruptPoll_Release,
428     ActiveScriptSiteInterruptPoll_QueryContinue
429 };
430
431 static inline ScriptHost *impl_from_IActiveScriptSiteWindow(IActiveScriptSiteWindow *iface)
432 {
433     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteWindow_iface);
434 }
435
436 static HRESULT WINAPI ActiveScriptSiteWindow_QueryInterface(IActiveScriptSiteWindow *iface,
437         REFIID riid, void **ppv)
438 {
439     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
440     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
441 }
442
443 static ULONG WINAPI ActiveScriptSiteWindow_AddRef(IActiveScriptSiteWindow *iface)
444 {
445     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
446     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
447 }
448
449 static ULONG WINAPI ActiveScriptSiteWindow_Release(IActiveScriptSiteWindow *iface)
450 {
451     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
452     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
453 }
454
455 static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *iface, HWND *phwnd)
456 {
457     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
458     FIXME("(%p)->(%p)\n", This, phwnd);
459     return E_NOTIMPL;
460 }
461
462 static HRESULT WINAPI ActiveScriptSiteWindow_EnableModeless(IActiveScriptSiteWindow *iface, BOOL fEnable)
463 {
464     ScriptHost *This = impl_from_IActiveScriptSiteWindow(iface);
465     FIXME("(%p)->(%x)\n", This, fEnable);
466     return E_NOTIMPL;
467 }
468
469 static const IActiveScriptSiteWindowVtbl ActiveScriptSiteWindowVtbl = {
470     ActiveScriptSiteWindow_QueryInterface,
471     ActiveScriptSiteWindow_AddRef,
472     ActiveScriptSiteWindow_Release,
473     ActiveScriptSiteWindow_GetWindow,
474     ActiveScriptSiteWindow_EnableModeless
475 };
476
477 static inline ScriptHost *impl_from_IActiveScriptSiteDebug(IActiveScriptSiteDebug *iface)
478 {
479     return CONTAINING_RECORD(iface, ScriptHost, IActiveScriptSiteDebug_iface);
480 }
481
482 static HRESULT WINAPI ActiveScriptSiteDebug_QueryInterface(IActiveScriptSiteDebug *iface,
483         REFIID riid, void **ppv)
484 {
485     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
486     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
487 }
488
489 static ULONG WINAPI ActiveScriptSiteDebug_AddRef(IActiveScriptSiteDebug *iface)
490 {
491     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
492     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
493 }
494
495 static ULONG WINAPI ActiveScriptSiteDebug_Release(IActiveScriptSiteDebug *iface)
496 {
497     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
498     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
499 }
500
501 static HRESULT WINAPI ActiveScriptSiteDebug_GetDocumentContextFromPosition(IActiveScriptSiteDebug *iface,
502             CTXARG_T dwSourceContext, ULONG uCharacterOffset, ULONG uNumChars, IDebugDocumentContext **ppsc)
503 {
504     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
505     FIXME("(%p)->(%s %u %u %p)\n", This, wine_dbgstr_longlong(dwSourceContext), uCharacterOffset,
506           uNumChars, ppsc);
507     return E_NOTIMPL;
508 }
509
510 static HRESULT WINAPI ActiveScriptSiteDebug_GetApplication(IActiveScriptSiteDebug *iface, IDebugApplication **ppda)
511 {
512     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
513     FIXME("(%p)->(%p)\n", This, ppda);
514     return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI ActiveScriptSiteDebug_GetRootApplicationNode(IActiveScriptSiteDebug *iface,
518             IDebugApplicationNode **ppdanRoot)
519 {
520     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
521     FIXME("(%p)->(%p)\n", This, ppdanRoot);
522     return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI ActiveScriptSiteDebug_OnScriptErrorDebug(IActiveScriptSiteDebug *iface,
526             IActiveScriptErrorDebug *pErrorDebug, BOOL *pfEnterDebugger, BOOL *pfCallOnScriptErrorWhenContinuing)
527 {
528     ScriptHost *This = impl_from_IActiveScriptSiteDebug(iface);
529     FIXME("(%p)->(%p %p %p)\n", This, pErrorDebug, pfEnterDebugger, pfCallOnScriptErrorWhenContinuing);
530     return E_NOTIMPL;
531 }
532
533 static const IActiveScriptSiteDebugVtbl ActiveScriptSiteDebugVtbl = {
534     ActiveScriptSiteDebug_QueryInterface,
535     ActiveScriptSiteDebug_AddRef,
536     ActiveScriptSiteDebug_Release,
537     ActiveScriptSiteDebug_GetDocumentContextFromPosition,
538     ActiveScriptSiteDebug_GetApplication,
539     ActiveScriptSiteDebug_GetRootApplicationNode,
540     ActiveScriptSiteDebug_OnScriptErrorDebug
541 };
542
543 static inline ScriptHost *impl_from_IServiceProvider(IServiceProvider *iface)
544 {
545     return CONTAINING_RECORD(iface, ScriptHost, IServiceProvider_iface);
546 }
547
548 static HRESULT WINAPI ASServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
549 {
550     ScriptHost *This = impl_from_IServiceProvider(iface);
551     return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, ppv);
552 }
553
554 static ULONG WINAPI ASServiceProvider_AddRef(IServiceProvider *iface)
555 {
556     ScriptHost *This = impl_from_IServiceProvider(iface);
557     return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
558 }
559
560 static ULONG WINAPI ASServiceProvider_Release(IServiceProvider *iface)
561 {
562     ScriptHost *This = impl_from_IServiceProvider(iface);
563     return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
564 }
565
566 static HRESULT WINAPI ASServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
567         REFIID riid, void **ppv)
568 {
569     ScriptHost *This = impl_from_IServiceProvider(iface);
570
571     if(IsEqualGUID(&SID_SInternetHostSecurityManager, guidService)) {
572         TRACE("(%p)->(SID_SInternetHostSecurityManager)\n", This);
573
574         if(!This->window || !This->window->doc)
575             return E_NOINTERFACE;
576
577         return IInternetHostSecurityManager_QueryInterface(&This->window->doc->IInternetHostSecurityManager_iface,
578                 riid, ppv);
579     }
580
581     FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
582     return E_NOINTERFACE;
583 }
584
585 static const IServiceProviderVtbl ASServiceProviderVtbl = {
586     ASServiceProvider_QueryInterface,
587     ASServiceProvider_AddRef,
588     ASServiceProvider_Release,
589     ASServiceProvider_QueryService
590 };
591
592 static ScriptHost *create_script_host(HTMLWindow *window, const GUID *guid)
593 {
594     ScriptHost *ret;
595     HRESULT hres;
596
597     ret = heap_alloc_zero(sizeof(*ret));
598     ret->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl;
599     ret->IActiveScriptSiteInterruptPoll_iface.lpVtbl = &ActiveScriptSiteInterruptPollVtbl;
600     ret->IActiveScriptSiteWindow_iface.lpVtbl = &ActiveScriptSiteWindowVtbl;
601     ret->IActiveScriptSiteDebug_iface.lpVtbl = &ActiveScriptSiteDebugVtbl;
602     ret->IServiceProvider_iface.lpVtbl = &ASServiceProviderVtbl;
603     ret->ref = 1;
604     ret->window = window;
605     ret->script_state = SCRIPTSTATE_UNINITIALIZED;
606
607     ret->guid = *guid;
608     list_add_tail(&window->script_hosts, &ret->entry);
609
610     hres = CoCreateInstance(&ret->guid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
611             &IID_IActiveScript, (void**)&ret->script);
612     if(FAILED(hres))
613         WARN("Could not load script engine: %08x\n", hres);
614     else if(!init_script_engine(ret))
615         release_script_engine(ret);
616
617     return ret;
618 }
619
620 static void parse_text(ScriptHost *script_host, LPCWSTR text)
621 {
622     EXCEPINFO excepinfo;
623     VARIANT var;
624     HRESULT hres;
625
626     static const WCHAR script_endW[] = {'<','/','S','C','R','I','P','T','>',0};
627
628     TRACE("%s\n", debugstr_w(text));
629
630     VariantInit(&var);
631     memset(&excepinfo, 0, sizeof(excepinfo));
632     TRACE(">>>\n");
633     hres = IActiveScriptParse64_ParseScriptText(script_host->parse, text, windowW, NULL, script_endW,
634                                               0, 0, SCRIPTTEXT_ISVISIBLE|SCRIPTTEXT_HOSTMANAGESSOURCE,
635                                               &var, &excepinfo);
636     if(SUCCEEDED(hres))
637         TRACE("<<<\n");
638     else
639         WARN("<<< %08x\n", hres);
640
641 }
642
643 static void parse_extern_script(ScriptHost *script_host, LPCWSTR src)
644 {
645     IMoniker *mon;
646     char *buf;
647     WCHAR *text;
648     DWORD len, size=0;
649     HRESULT hres;
650
651     static const WCHAR wine_schemaW[] = {'w','i','n','e',':'};
652
653     if(strlenW(src) > sizeof(wine_schemaW)/sizeof(WCHAR) && !memcmp(src, wine_schemaW, sizeof(wine_schemaW)))
654         src += sizeof(wine_schemaW)/sizeof(WCHAR);
655
656     hres = CreateURLMoniker(NULL, src, &mon);
657     if(FAILED(hres))
658         return;
659
660     hres = bind_mon_to_buffer(script_host->window->doc, mon, (void**)&buf, &size);
661     IMoniker_Release(mon);
662     if(FAILED(hres))
663         return;
664
665     len = MultiByteToWideChar(CP_ACP, 0, buf, size, NULL, 0);
666     text = heap_alloc((len+1)*sizeof(WCHAR));
667     MultiByteToWideChar(CP_ACP, 0, buf, size, text, len);
668     heap_free(buf);
669     text[len] = 0;
670
671     parse_text(script_host, text);
672
673     heap_free(text);
674 }
675
676 static void parse_inline_script(ScriptHost *script_host, nsIDOMHTMLScriptElement *nsscript)
677 {
678     const PRUnichar *text;
679     nsAString text_str;
680     nsresult nsres;
681
682     nsAString_Init(&text_str, NULL);
683
684     nsres = nsIDOMHTMLScriptElement_GetText(nsscript, &text_str);
685
686     if(NS_SUCCEEDED(nsres)) {
687         nsAString_GetData(&text_str, &text);
688         parse_text(script_host, text);
689     }else {
690         ERR("GetText failed: %08x\n", nsres);
691     }
692
693     nsAString_Finish(&text_str);
694 }
695
696 static void parse_script_elem(ScriptHost *script_host, nsIDOMHTMLScriptElement *nsscript)
697 {
698     const PRUnichar *src;
699     nsAString src_str;
700     nsresult nsres;
701
702     nsAString_Init(&src_str, NULL);
703
704     nsres = nsIDOMHTMLScriptElement_GetSrc(nsscript, &src_str);
705     nsAString_GetData(&src_str, &src);
706
707     if(NS_FAILED(nsres))
708         ERR("GetSrc failed: %08x\n", nsres);
709     else if(*src)
710         parse_extern_script(script_host, src);
711     else
712         parse_inline_script(script_host, nsscript);
713
714     nsAString_Finish(&src_str);
715 }
716
717 static BOOL get_guid_from_type(LPCWSTR type, GUID *guid)
718 {
719     const WCHAR text_javascriptW[] =
720         {'t','e','x','t','/','j','a','v','a','s','c','r','i','p','t',0};
721
722     /* FIXME: Handle more types */
723     if(!strcmpiW(type, text_javascriptW)) {
724         *guid = CLSID_JScript;
725     }else {
726         FIXME("Unknown type %s\n", debugstr_w(type));
727         return FALSE;
728     }
729
730     return TRUE;
731 }
732
733 static BOOL get_guid_from_language(LPCWSTR type, GUID *guid)
734 {
735     HRESULT hres;
736
737     hres = CLSIDFromProgID(type, guid);
738     if(FAILED(hres))
739         return FALSE;
740
741     /* FIXME: Check CATID_ActiveScriptParse */
742
743     return TRUE;
744 }
745
746 static BOOL get_script_guid(nsIDOMHTMLScriptElement *nsscript, GUID *guid)
747 {
748     nsAString attr_str, val_str;
749     BOOL ret = FALSE;
750     nsresult nsres;
751
752     static const PRUnichar languageW[] = {'l','a','n','g','u','a','g','e',0};
753
754     nsAString_Init(&val_str, NULL);
755
756     nsres = nsIDOMHTMLScriptElement_GetType(nsscript, &val_str);
757     if(NS_SUCCEEDED(nsres)) {
758         const PRUnichar *type;
759
760         nsAString_GetData(&val_str, &type);
761         if(*type) {
762             ret = get_guid_from_type(type, guid);
763             nsAString_Finish(&val_str);
764             return ret;
765         }
766     }else {
767         ERR("GetType failed: %08x\n", nsres);
768     }
769
770     nsAString_InitDepend(&attr_str, languageW);
771     nsres = nsIDOMHTMLScriptElement_GetAttribute(nsscript, &attr_str, &val_str);
772     nsAString_Finish(&attr_str);
773     if(NS_SUCCEEDED(nsres)) {
774         const PRUnichar *language;
775
776         nsAString_GetData(&val_str, &language);
777
778         if(*language) {
779             ret = get_guid_from_language(language, guid);
780         }else {
781             *guid = CLSID_JScript;
782             ret = TRUE;
783         }
784     }else {
785         ERR("GetAttribute(language) failed: %08x\n", nsres);
786     }
787
788     nsAString_Finish(&val_str);
789
790     return ret;
791 }
792
793 static ScriptHost *get_script_host(HTMLWindow *window, const GUID *guid)
794 {
795     ScriptHost *iter;
796
797     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
798         if(IsEqualGUID(guid, &iter->guid))
799             return iter;
800     }
801
802     return create_script_host(window, guid);
803 }
804
805 void doc_insert_script(HTMLWindow *window, nsIDOMHTMLScriptElement *nsscript)
806 {
807     ScriptHost *script_host;
808     GUID guid;
809
810     if(!get_script_guid(nsscript, &guid)) {
811         WARN("Could not find script GUID\n");
812         return;
813     }
814
815     if(IsEqualGUID(&CLSID_JScript, &guid) && window->scriptmode != SCRIPTMODE_ACTIVESCRIPT) {
816         TRACE("Ignoring JScript\n");
817         return;
818     }
819
820     script_host = get_script_host(window, &guid);
821     if(!script_host)
822         return;
823
824     if(script_host->parse)
825         parse_script_elem(script_host, nsscript);
826 }
827
828 IDispatch *script_parse_event(HTMLWindow *window, LPCWSTR text)
829 {
830     ScriptHost *script_host;
831     GUID guid = CLSID_JScript;
832     const WCHAR *ptr;
833     IDispatch *disp;
834     HRESULT hres;
835
836     static const WCHAR delimiterW[] = {'\"',0};
837
838     for(ptr = text; isalnumW(*ptr); ptr++);
839     if(*ptr == ':') {
840         LPWSTR language;
841         BOOL b;
842
843         language = heap_alloc((ptr-text+1)*sizeof(WCHAR));
844         memcpy(language, text, (ptr-text)*sizeof(WCHAR));
845         language[ptr-text] = 0;
846
847         b = get_guid_from_language(language, &guid);
848
849         heap_free(language);
850
851         if(!b) {
852             WARN("Could not find language\n");
853             return NULL;
854         }
855
856         ptr++;
857     }else {
858         ptr = text;
859     }
860
861     if(IsEqualGUID(&CLSID_JScript, &guid) && window->scriptmode != SCRIPTMODE_ACTIVESCRIPT) {
862         TRACE("Ignoring JScript\n");
863         return NULL;
864     }
865
866     script_host = get_script_host(window, &guid);
867     if(!script_host || !script_host->parse_proc)
868         return NULL;
869
870     hres = IActiveScriptParseProcedure64_ParseProcedureText(script_host->parse_proc, ptr, NULL, emptyW,
871             NULL, NULL, delimiterW, 0 /* FIXME */, 0,
872             SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp);
873     if(FAILED(hres)) {
874         WARN("ParseProcedureText failed: %08x\n", hres);
875         return NULL;
876     }
877
878     TRACE("ret %p\n", disp);
879     return disp;
880 }
881
882 HRESULT exec_script(HTMLWindow *window, const WCHAR *code, const WCHAR *lang, VARIANT *ret)
883 {
884     ScriptHost *script_host;
885     EXCEPINFO ei;
886     GUID guid;
887     HRESULT hres;
888
889     static const WCHAR delimW[] = {'"',0};
890
891     if(!get_guid_from_language(lang, &guid)) {
892         WARN("Could not find script GUID\n");
893         return CO_E_CLASSSTRING;
894     }
895
896     script_host = get_script_host(window, &guid);
897     if(!script_host) {
898         FIXME("No script host\n");
899         return E_FAIL;
900     }
901
902     if(!script_host->parse) {
903         FIXME("script_host->parse == NULL\n");
904         return E_FAIL;
905     }
906
907     memset(&ei, 0, sizeof(ei));
908     TRACE(">>>\n");
909     hres = IActiveScriptParse64_ParseScriptText(script_host->parse, code, NULL, NULL, delimW, 0, 0, SCRIPTTEXT_ISVISIBLE, ret, &ei);
910     if(SUCCEEDED(hres))
911         TRACE("<<<\n");
912     else
913         WARN("<<< %08x\n", hres);
914
915     return hres;
916 }
917
918 IDispatch *get_script_disp(ScriptHost *script_host)
919 {
920     IDispatch *disp;
921     HRESULT hres;
922
923     if(!script_host->script)
924         return NULL;
925
926     hres = IActiveScript_GetScriptDispatch(script_host->script, windowW, &disp);
927     if(FAILED(hres))
928         return NULL;
929
930     return disp;
931 }
932
933 BOOL find_global_prop(HTMLWindow *window, BSTR name, DWORD flags, ScriptHost **ret_host, DISPID *ret_id)
934 {
935     IDispatchEx *dispex;
936     IDispatch *disp;
937     ScriptHost *iter;
938     HRESULT hres;
939
940     LIST_FOR_EACH_ENTRY(iter, &window->script_hosts, ScriptHost, entry) {
941         disp = get_script_disp(iter);
942         if(!disp)
943             continue;
944
945         hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
946         if(SUCCEEDED(hres)) {
947             hres = IDispatchEx_GetDispID(dispex, name, flags & (~fdexNameEnsure), ret_id);
948             IDispatchEx_Release(dispex);
949         }else {
950             FIXME("No IDispatchEx\n");
951             hres = E_NOTIMPL;
952         }
953
954         IDispatch_Release(disp);
955         if(SUCCEEDED(hres)) {
956             *ret_host = iter;
957             return TRUE;
958         }
959     }
960
961     return FALSE;
962 }
963
964 static BOOL is_jscript_available(void)
965 {
966     static BOOL available, checked;
967
968     if(!checked) {
969         IUnknown *unk;
970         HRESULT hres = CoGetClassObject(&CLSID_JScript, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
971
972         if(SUCCEEDED(hres)) {
973             available = TRUE;
974             IUnknown_Release(unk);
975         }else {
976             available = FALSE;
977         }
978         checked = TRUE;
979     }
980
981     return available;
982 }
983
984 void set_script_mode(HTMLWindow *window, SCRIPTMODE mode)
985 {
986     nsIWebBrowserSetup *setup;
987     nsresult nsres;
988
989     if(mode == SCRIPTMODE_ACTIVESCRIPT && !is_jscript_available()) {
990         TRACE("jscript.dll not available\n");
991         window->scriptmode = SCRIPTMODE_GECKO;
992         return;
993     }
994
995     window->scriptmode = mode;
996
997     if(!window->doc_obj->nscontainer || !window->doc_obj->nscontainer->webbrowser)
998         return;
999
1000     nsres = nsIWebBrowser_QueryInterface(window->doc_obj->nscontainer->webbrowser,
1001             &IID_nsIWebBrowserSetup, (void**)&setup);
1002     if(NS_SUCCEEDED(nsres)) {
1003         nsres = nsIWebBrowserSetup_SetProperty(setup, SETUP_ALLOW_JAVASCRIPT,
1004                 window->scriptmode == SCRIPTMODE_GECKO);
1005         nsIWebBrowserSetup_Release(setup);
1006     }
1007
1008     if(NS_FAILED(nsres))
1009         ERR("JavaScript setup failed: %08x\n", nsres);
1010 }
1011
1012 void release_script_hosts(HTMLWindow *window)
1013 {
1014     ScriptHost *iter;
1015
1016     while(!list_empty(&window->script_hosts)) {
1017         iter = LIST_ENTRY(list_head(&window->script_hosts), ScriptHost, entry);
1018
1019         release_script_engine(iter);
1020         list_remove(&iter->entry);
1021         iter->window = NULL;
1022         IActiveScript_Release(&iter->IActiveScriptSite_iface);
1023     }
1024 }