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, &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);
323 FIXME("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
327 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
328 DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
330 JScript *This = ACTSCRIPT_THIS(iface);
331 FIXME("(%p)->()\n", This);
335 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
338 JScript *This = ACTSCRIPT_THIS(iface);
340 TRACE("(%p)->(%p)\n", This, ppdisp);
345 if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) {
350 *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp);
351 IDispatch_AddRef(*ppdisp);
355 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
356 SCRIPTTHREADID *pstridThread)
358 JScript *This = ACTSCRIPT_THIS(iface);
359 FIXME("(%p)->()\n", This);
363 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
364 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
366 JScript *This = ACTSCRIPT_THIS(iface);
367 FIXME("(%p)->()\n", This);
371 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
372 SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
374 JScript *This = ACTSCRIPT_THIS(iface);
375 FIXME("(%p)->()\n", This);
379 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
380 SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
382 JScript *This = ACTSCRIPT_THIS(iface);
383 FIXME("(%p)->()\n", This);
387 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
389 JScript *This = ACTSCRIPT_THIS(iface);
390 FIXME("(%p)->()\n", This);
394 #undef ACTSCRIPT_THIS
396 static const IActiveScriptVtbl JScriptVtbl = {
397 JScript_QueryInterface,
400 JScript_SetScriptSite,
401 JScript_GetScriptSite,
402 JScript_SetScriptState,
403 JScript_GetScriptState,
405 JScript_AddNamedItem,
407 JScript_GetScriptDispatch,
408 JScript_GetCurrentScriptThreadID,
409 JScript_GetScriptThreadID,
410 JScript_GetScriptThreadState,
411 JScript_InterruptScriptThread,
415 #define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
417 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
419 JScript *This = ASPARSE_THIS(iface);
420 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
423 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
425 JScript *This = ASPARSE_THIS(iface);
426 return IActiveScript_AddRef(ACTSCRIPT(This));
429 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
431 JScript *This = ASPARSE_THIS(iface);
432 return IActiveScript_Release(ACTSCRIPT(This));
435 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
437 JScript *This = ASPARSE_THIS(iface);
440 TRACE("(%p)\n", This);
445 ctx = heap_alloc_zero(sizeof(script_ctx_t));
447 return E_OUTOFMEMORY;
450 ctx->state = SCRIPTSTATE_UNINITIALIZED;
452 ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
461 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
462 LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
463 LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
464 DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
465 BSTR *pbstrName, EXCEPINFO *pexcepinfo)
467 JScript *This = ASPARSE_THIS(iface);
468 FIXME("(%p)->(%s %s %s %s %s %s %x %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
469 debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
470 debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), dwSourceContextCookie,
471 ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
475 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
476 LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
477 LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLine,
478 DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
480 JScript *This = ASPARSE_THIS(iface);
481 parser_ctx_t *parser_ctx;
484 TRACE("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode),
485 debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
486 dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo);
488 if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
491 hres = script_parse(This->ctx, pstrCode, &parser_ctx);
495 if(!is_started(This->ctx)) {
497 This->queue_tail = This->queue_tail->next = parser_ctx;
499 This->queue_head = This->queue_tail = parser_ctx;
503 hres = exec_global_code(This, parser_ctx);
504 parser_release(parser_ctx);
511 static const IActiveScriptParseVtbl JScriptParseVtbl = {
512 JScriptParse_QueryInterface,
514 JScriptParse_Release,
515 JScriptParse_InitNew,
516 JScriptParse_AddScriptlet,
517 JScriptParse_ParseScriptText
520 #define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
522 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
524 JScript *This = ASPARSEPROC_THIS(iface);
525 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
528 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
530 JScript *This = ASPARSEPROC_THIS(iface);
531 return IActiveScript_AddRef(ACTSCRIPT(This));
534 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
536 JScript *This = ASPARSEPROC_THIS(iface);
537 return IActiveScript_Release(ACTSCRIPT(This));
540 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
541 LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
542 LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
543 DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
545 JScript *This = ASPARSEPROC_THIS(iface);
546 FIXME("(%p)->()\n", This);
550 #undef ASPARSEPROC_THIS
552 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
553 JScriptParseProcedure_QueryInterface,
554 JScriptParseProcedure_AddRef,
555 JScriptParseProcedure_Release,
556 JScriptParseProcedure_ParseProcedureText,
559 #define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
561 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
563 JScript *This = ACTSCPPROP_THIS(iface);
564 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
567 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
569 JScript *This = ACTSCPPROP_THIS(iface);
570 return IActiveScript_AddRef(ACTSCRIPT(This));
573 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
575 JScript *This = ACTSCPPROP_THIS(iface);
576 return IActiveScript_Release(ACTSCRIPT(This));
579 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
580 VARIANT *pvarIndex, VARIANT *pvarValue)
582 JScript *This = ACTSCPPROP_THIS(iface);
583 FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
587 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
588 VARIANT *pvarIndex, VARIANT *pvarValue)
590 JScript *This = ACTSCPPROP_THIS(iface);
591 FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
595 #undef ACTSCPPROP_THIS
597 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
598 JScriptProperty_QueryInterface,
599 JScriptProperty_AddRef,
600 JScriptProperty_Release,
601 JScriptProperty_GetProperty,
602 JScriptProperty_SetProperty
605 #define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
607 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
609 JScript *This = OBJSAFETY_THIS(iface);
610 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
613 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
615 JScript *This = OBJSAFETY_THIS(iface);
616 return IActiveScript_AddRef(ACTSCRIPT(This));
619 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
621 JScript *This = OBJSAFETY_THIS(iface);
622 return IActiveScript_Release(ACTSCRIPT(This));
625 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
627 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
628 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
630 JScript *This = OBJSAFETY_THIS(iface);
632 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
634 if(!pdwSupportedOptions || !pdwEnabledOptions)
637 *pdwSupportedOptions = SUPPORTED_OPTIONS;
638 *pdwEnabledOptions = This->safeopt;
643 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
644 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
646 JScript *This = OBJSAFETY_THIS(iface);
648 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
650 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
653 This->safeopt = dwEnabledOptions & dwEnabledOptions;
657 #undef OBJSAFETY_THIS
659 static const IObjectSafetyVtbl JScriptSafetyVtbl = {
660 JScriptSafety_QueryInterface,
661 JScriptSafety_AddRef,
662 JScriptSafety_Release,
663 JScriptSafety_GetInterfaceSafetyOptions,
664 JScriptSafety_SetInterfaceSafetyOptions
667 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
668 REFIID riid, void **ppv)
673 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
677 ret = heap_alloc_zero(sizeof(*ret));
679 ret->lpIActiveScriptVtbl = &JScriptVtbl;
680 ret->lpIActiveScriptParseVtbl = &JScriptParseVtbl;
681 ret->lpIActiveScriptParseProcedure2Vtbl = &JScriptParseProcedureVtbl;
682 ret->lpIActiveScriptPropertyVtbl = &JScriptPropertyVtbl;
683 ret->lpIObjectSafetyVtbl = &JScriptSafetyVtbl;
685 ret->safeopt = INTERFACE_USES_DISPEX;
687 hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
688 IActiveScript_Release(ACTSCRIPT(ret));