2 * Copyright 2008 Jacek Caban for CodeWeavers
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.
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.
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
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
28 const IActiveScriptVtbl *lpIActiveScriptVtbl;
29 const IActiveScriptParseVtbl *lpIActiveScriptParseVtbl;
30 const IActiveScriptParseProcedure2Vtbl *lpIActiveScriptParseProcedure2Vtbl;
31 const IActiveScriptPropertyVtbl *lpIActiveScriptPropertyVtbl;
32 const IObjectSafetyVtbl *lpIObjectSafetyVtbl;
40 IActiveScriptSite *site;
42 parser_ctx_t *queue_head;
43 parser_ctx_t *queue_tail;
46 #define ACTSCRIPT(x) ((IActiveScript*) &(x)->lpIActiveScriptVtbl)
47 #define ASPARSE(x) ((IActiveScriptParse*) &(x)->lpIActiveScriptParseVtbl)
48 #define ASPARSEPROC(x) ((IActiveScriptParseProcedure2*) &(x)->lpIActiveScriptParseProcedure2Vtbl)
49 #define ACTSCPPROP(x) ((IActiveScriptProperty*) &(x)->lpIActiveScriptPropertyVtbl)
50 #define OBJSAFETY(x) ((IObjectSafety*) &(x)->lpIObjectSafetyVtbl)
52 void script_release(script_ctx_t *ctx)
60 static void change_state(JScript *This, SCRIPTSTATE state)
62 if(This->ctx->state == state)
65 This->ctx->state = state;
66 IActiveScriptSite_OnStateChange(This->site, state);
69 static inline BOOL is_started(script_ctx_t *ctx)
71 return ctx->state == SCRIPTSTATE_STARTED
72 || ctx->state == SCRIPTSTATE_CONNECTED
73 || ctx->state == SCRIPTSTATE_DISCONNECTED;
76 static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx)
83 hres = create_exec_ctx(&exec_ctx);
87 IActiveScriptSite_OnEnterScript(This->site);
89 memset(&jsexcept, 0, sizeof(jsexcept));
90 hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, &jsexcept, &var);
91 VariantClear(&jsexcept.var);
92 exec_release(exec_ctx);
96 IActiveScriptSite_OnLeaveScript(This->site);
101 static void clear_script_queue(JScript *This)
103 parser_ctx_t *iter, *iter2;
105 if(!This->queue_head)
108 iter = This->queue_head;
112 parser_release(iter);
116 This->queue_head = This->queue_tail = NULL;
119 static void exec_queued_code(JScript *This)
123 for(iter = This->queue_head; iter; iter = iter->next)
124 exec_global_code(This, iter);
126 clear_script_queue(This);
129 #define ACTSCRIPT_THIS(iface) DEFINE_THIS(JScript, IActiveScript, iface)
131 static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
133 JScript *This = ACTSCRIPT_THIS(iface);
137 if(IsEqualGUID(riid, &IID_IUnknown)) {
138 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
139 *ppv = ACTSCRIPT(This);
140 }else if(IsEqualGUID(riid, &IID_IActiveScript)) {
141 TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv);
142 *ppv = ACTSCRIPT(This);
143 }else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) {
144 TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv);
145 *ppv = ASPARSE(This);
146 }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure)) {
147 TRACE("(%p)->(IID_IActiveScriptParseProcedure %p)\n", This, ppv);
148 *ppv = ASPARSEPROC(This);
149 }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure2)) {
150 TRACE("(%p)->(IID_IActiveScriptParseProcedure2 %p)\n", This, ppv);
151 *ppv = ASPARSEPROC(This);
152 }else if(IsEqualGUID(riid, &IID_IActiveScriptProperty)) {
153 TRACE("(%p)->(IID_IActiveScriptProperty %p)\n", This, ppv);
154 *ppv = ACTSCPPROP(This);
155 }else if(IsEqualGUID(riid, &IID_IObjectSafety)) {
156 TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
157 *ppv = OBJSAFETY(This);
161 IUnknown_AddRef((IUnknown*)*ppv);
165 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
166 return E_NOINTERFACE;
169 static ULONG WINAPI JScript_AddRef(IActiveScript *iface)
171 JScript *This = ACTSCRIPT_THIS(iface);
172 LONG ref = InterlockedIncrement(&This->ref);
174 TRACE("(%p) ref=%d\n", This, ref);
179 static ULONG WINAPI JScript_Release(IActiveScript *iface)
181 JScript *This = ACTSCRIPT_THIS(iface);
182 LONG ref = InterlockedDecrement(&This->ref);
184 TRACE("(%p) ref=%d\n", iface, ref);
187 if(This->ctx && This->ctx->state != SCRIPTSTATE_CLOSED)
188 IActiveScript_Close(ACTSCRIPT(This));
190 script_release(This->ctx);
198 static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
199 IActiveScriptSite *pass)
201 JScript *This = ACTSCRIPT_THIS(iface);
205 TRACE("(%p)->(%p)\n", This, pass);
214 hres = IActiveScriptParse_InitNew(ASPARSE(This));
219 hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp);
223 if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
227 IActiveScriptSite_AddRef(This->site);
229 hres = IActiveScriptSite_GetLCID(This->site, &lcid);
231 This->ctx->lcid = lcid;
233 change_state(This, SCRIPTSTATE_INITIALIZED);
237 static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid,
240 JScript *This = ACTSCRIPT_THIS(iface);
241 FIXME("(%p)->()\n", This);
245 static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
247 JScript *This = ACTSCRIPT_THIS(iface);
249 TRACE("(%p)->(%d)\n", This, ss);
251 if(!This->ctx || GetCurrentThreadId() != This->thread_id)
255 case SCRIPTSTATE_STARTED:
256 if(This->ctx->state == SCRIPTSTATE_CLOSED)
259 exec_queued_code(This);
262 FIXME("unimplemented state %d\n", ss);
266 change_state(This, ss);
270 static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
272 JScript *This = ACTSCRIPT_THIS(iface);
274 TRACE("(%p)->(%p)\n", This, pssState);
279 if(!This->thread_id) {
280 *pssState = SCRIPTSTATE_UNINITIALIZED;
284 if(This->thread_id != GetCurrentThreadId())
287 *pssState = This->ctx ? This->ctx->state : SCRIPTSTATE_UNINITIALIZED;
291 static HRESULT WINAPI JScript_Close(IActiveScript *iface)
293 JScript *This = ACTSCRIPT_THIS(iface);
295 TRACE("(%p)->()\n", This);
297 if(This->thread_id != GetCurrentThreadId())
300 clear_script_queue(This);
303 change_state(This, SCRIPTSTATE_CLOSED);
305 if(This->ctx->script_disp) {
306 IDispatchEx_Release(_IDispatchEx_(This->ctx->script_disp));
307 This->ctx->script_disp = NULL;
312 IActiveScriptSite_Release(This->site);
319 static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
320 LPCOLESTR pstrName, DWORD dwFlags)
322 JScript *This = ACTSCRIPT_THIS(iface);
328 TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
330 if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->ctx->state == SCRIPTSTATE_CLOSED)
333 hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
335 WARN("GetItemInfo failed: %08x\n", hres);
339 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
340 IUnknown_Release(unk);
342 WARN("object does not implement IDispatch\n");
346 item = heap_alloc(sizeof(*item));
348 IDispatch_Release(disp);
349 return E_OUTOFMEMORY;
353 item->flags = dwFlags;
354 item->next = This->ctx->named_items;
355 This->ctx->named_items = item;
360 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
361 DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
363 JScript *This = ACTSCRIPT_THIS(iface);
364 FIXME("(%p)->()\n", This);
368 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
371 JScript *This = ACTSCRIPT_THIS(iface);
373 TRACE("(%p)->(%p)\n", This, ppdisp);
378 if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) {
383 *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp);
384 IDispatch_AddRef(*ppdisp);
388 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
389 SCRIPTTHREADID *pstridThread)
391 JScript *This = ACTSCRIPT_THIS(iface);
392 FIXME("(%p)->()\n", This);
396 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
397 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
399 JScript *This = ACTSCRIPT_THIS(iface);
400 FIXME("(%p)->()\n", This);
404 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
405 SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
407 JScript *This = ACTSCRIPT_THIS(iface);
408 FIXME("(%p)->()\n", This);
412 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
413 SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
415 JScript *This = ACTSCRIPT_THIS(iface);
416 FIXME("(%p)->()\n", This);
420 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
422 JScript *This = ACTSCRIPT_THIS(iface);
423 FIXME("(%p)->()\n", This);
427 #undef ACTSCRIPT_THIS
429 static const IActiveScriptVtbl JScriptVtbl = {
430 JScript_QueryInterface,
433 JScript_SetScriptSite,
434 JScript_GetScriptSite,
435 JScript_SetScriptState,
436 JScript_GetScriptState,
438 JScript_AddNamedItem,
440 JScript_GetScriptDispatch,
441 JScript_GetCurrentScriptThreadID,
442 JScript_GetScriptThreadID,
443 JScript_GetScriptThreadState,
444 JScript_InterruptScriptThread,
448 #define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
450 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
452 JScript *This = ASPARSE_THIS(iface);
453 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
456 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
458 JScript *This = ASPARSE_THIS(iface);
459 return IActiveScript_AddRef(ACTSCRIPT(This));
462 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
464 JScript *This = ASPARSE_THIS(iface);
465 return IActiveScript_Release(ACTSCRIPT(This));
468 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
470 JScript *This = ASPARSE_THIS(iface);
473 TRACE("(%p)\n", This);
478 ctx = heap_alloc_zero(sizeof(script_ctx_t));
480 return E_OUTOFMEMORY;
483 ctx->state = SCRIPTSTATE_UNINITIALIZED;
485 ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
494 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
495 LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
496 LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
497 DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
498 BSTR *pbstrName, EXCEPINFO *pexcepinfo)
500 JScript *This = ASPARSE_THIS(iface);
501 FIXME("(%p)->(%s %s %s %s %s %s %x %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
502 debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
503 debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), dwSourceContextCookie,
504 ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
508 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
509 LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
510 LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLine,
511 DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
513 JScript *This = ASPARSE_THIS(iface);
514 parser_ctx_t *parser_ctx;
517 TRACE("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode),
518 debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
519 dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo);
521 if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
524 hres = script_parse(This->ctx, pstrCode, &parser_ctx);
528 if(!is_started(This->ctx)) {
530 This->queue_tail = This->queue_tail->next = parser_ctx;
532 This->queue_head = This->queue_tail = parser_ctx;
536 hres = exec_global_code(This, parser_ctx);
537 parser_release(parser_ctx);
544 static const IActiveScriptParseVtbl JScriptParseVtbl = {
545 JScriptParse_QueryInterface,
547 JScriptParse_Release,
548 JScriptParse_InitNew,
549 JScriptParse_AddScriptlet,
550 JScriptParse_ParseScriptText
553 #define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
555 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
557 JScript *This = ASPARSEPROC_THIS(iface);
558 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
561 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
563 JScript *This = ASPARSEPROC_THIS(iface);
564 return IActiveScript_AddRef(ACTSCRIPT(This));
567 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
569 JScript *This = ASPARSEPROC_THIS(iface);
570 return IActiveScript_Release(ACTSCRIPT(This));
573 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
574 LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
575 LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
576 DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
578 JScript *This = ASPARSEPROC_THIS(iface);
579 FIXME("(%p)->()\n", This);
583 #undef ASPARSEPROC_THIS
585 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
586 JScriptParseProcedure_QueryInterface,
587 JScriptParseProcedure_AddRef,
588 JScriptParseProcedure_Release,
589 JScriptParseProcedure_ParseProcedureText,
592 #define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
594 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
596 JScript *This = ACTSCPPROP_THIS(iface);
597 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
600 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
602 JScript *This = ACTSCPPROP_THIS(iface);
603 return IActiveScript_AddRef(ACTSCRIPT(This));
606 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
608 JScript *This = ACTSCPPROP_THIS(iface);
609 return IActiveScript_Release(ACTSCRIPT(This));
612 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
613 VARIANT *pvarIndex, VARIANT *pvarValue)
615 JScript *This = ACTSCPPROP_THIS(iface);
616 FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
620 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
621 VARIANT *pvarIndex, VARIANT *pvarValue)
623 JScript *This = ACTSCPPROP_THIS(iface);
624 FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
628 #undef ACTSCPPROP_THIS
630 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
631 JScriptProperty_QueryInterface,
632 JScriptProperty_AddRef,
633 JScriptProperty_Release,
634 JScriptProperty_GetProperty,
635 JScriptProperty_SetProperty
638 #define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
640 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
642 JScript *This = OBJSAFETY_THIS(iface);
643 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
646 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
648 JScript *This = OBJSAFETY_THIS(iface);
649 return IActiveScript_AddRef(ACTSCRIPT(This));
652 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
654 JScript *This = OBJSAFETY_THIS(iface);
655 return IActiveScript_Release(ACTSCRIPT(This));
658 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
660 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
661 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
663 JScript *This = OBJSAFETY_THIS(iface);
665 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
667 if(!pdwSupportedOptions || !pdwEnabledOptions)
670 *pdwSupportedOptions = SUPPORTED_OPTIONS;
671 *pdwEnabledOptions = This->safeopt;
676 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
677 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
679 JScript *This = OBJSAFETY_THIS(iface);
681 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
683 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
686 This->safeopt = dwEnabledOptions & dwEnabledOptions;
690 #undef OBJSAFETY_THIS
692 static const IObjectSafetyVtbl JScriptSafetyVtbl = {
693 JScriptSafety_QueryInterface,
694 JScriptSafety_AddRef,
695 JScriptSafety_Release,
696 JScriptSafety_GetInterfaceSafetyOptions,
697 JScriptSafety_SetInterfaceSafetyOptions
700 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
701 REFIID riid, void **ppv)
706 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
710 ret = heap_alloc_zero(sizeof(*ret));
712 ret->lpIActiveScriptVtbl = &JScriptVtbl;
713 ret->lpIActiveScriptParseVtbl = &JScriptParseVtbl;
714 ret->lpIActiveScriptParseProcedure2Vtbl = &JScriptParseProcedureVtbl;
715 ret->lpIActiveScriptPropertyVtbl = &JScriptPropertyVtbl;
716 ret->lpIObjectSafetyVtbl = &JScriptSafetyVtbl;
718 ret->safeopt = INTERFACE_USES_DISPEX;
720 hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
721 IActiveScript_Release(ACTSCRIPT(ret));