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((IDispatch*)_IDispatchEx_(This->ctx->script_disp), This->ctx->script_disp, NULL, &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 if(!This->ctx->script_disp) {
220 hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp);
225 hres = init_global(This->ctx);
229 if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
233 IActiveScriptSite_AddRef(This->site);
235 hres = IActiveScriptSite_GetLCID(This->site, &lcid);
237 This->ctx->lcid = lcid;
239 change_state(This, SCRIPTSTATE_INITIALIZED);
243 static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid,
246 JScript *This = ACTSCRIPT_THIS(iface);
247 FIXME("(%p)->()\n", This);
251 static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
253 JScript *This = ACTSCRIPT_THIS(iface);
255 TRACE("(%p)->(%d)\n", This, ss);
257 if(!This->ctx || GetCurrentThreadId() != This->thread_id)
261 case SCRIPTSTATE_STARTED:
262 if(This->ctx->state == SCRIPTSTATE_CLOSED)
265 exec_queued_code(This);
268 FIXME("unimplemented state %d\n", ss);
272 change_state(This, ss);
276 static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
278 JScript *This = ACTSCRIPT_THIS(iface);
280 TRACE("(%p)->(%p)\n", This, pssState);
285 if(!This->thread_id) {
286 *pssState = SCRIPTSTATE_UNINITIALIZED;
290 if(This->thread_id != GetCurrentThreadId())
293 *pssState = This->ctx ? This->ctx->state : SCRIPTSTATE_UNINITIALIZED;
297 static HRESULT WINAPI JScript_Close(IActiveScript *iface)
299 JScript *This = ACTSCRIPT_THIS(iface);
301 TRACE("(%p)->()\n", This);
303 if(This->thread_id != GetCurrentThreadId())
306 clear_script_queue(This);
309 change_state(This, SCRIPTSTATE_CLOSED);
311 if(This->ctx->script_disp) {
312 IDispatchEx_Release(_IDispatchEx_(This->ctx->script_disp));
313 This->ctx->script_disp = NULL;
316 if(This->ctx->global) {
317 IDispatchEx_Release(_IDispatchEx_(This->ctx->global));
318 This->ctx->global = NULL;
323 IActiveScriptSite_Release(This->site);
330 static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
331 LPCOLESTR pstrName, DWORD dwFlags)
333 JScript *This = ACTSCRIPT_THIS(iface);
339 TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
341 if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->ctx->state == SCRIPTSTATE_CLOSED)
344 hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
346 WARN("GetItemInfo failed: %08x\n", hres);
350 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
351 IUnknown_Release(unk);
353 WARN("object does not implement IDispatch\n");
357 item = heap_alloc(sizeof(*item));
359 IDispatch_Release(disp);
360 return E_OUTOFMEMORY;
364 item->flags = dwFlags;
365 item->next = This->ctx->named_items;
366 This->ctx->named_items = item;
371 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
372 DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
374 JScript *This = ACTSCRIPT_THIS(iface);
375 FIXME("(%p)->()\n", This);
379 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
382 JScript *This = ACTSCRIPT_THIS(iface);
384 TRACE("(%p)->(%p)\n", This, ppdisp);
389 if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) {
394 *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp);
395 IDispatch_AddRef(*ppdisp);
399 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
400 SCRIPTTHREADID *pstridThread)
402 JScript *This = ACTSCRIPT_THIS(iface);
403 FIXME("(%p)->()\n", This);
407 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
408 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
410 JScript *This = ACTSCRIPT_THIS(iface);
411 FIXME("(%p)->()\n", This);
415 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
416 SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
418 JScript *This = ACTSCRIPT_THIS(iface);
419 FIXME("(%p)->()\n", This);
423 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
424 SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
426 JScript *This = ACTSCRIPT_THIS(iface);
427 FIXME("(%p)->()\n", This);
431 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
433 JScript *This = ACTSCRIPT_THIS(iface);
434 FIXME("(%p)->()\n", This);
438 #undef ACTSCRIPT_THIS
440 static const IActiveScriptVtbl JScriptVtbl = {
441 JScript_QueryInterface,
444 JScript_SetScriptSite,
445 JScript_GetScriptSite,
446 JScript_SetScriptState,
447 JScript_GetScriptState,
449 JScript_AddNamedItem,
451 JScript_GetScriptDispatch,
452 JScript_GetCurrentScriptThreadID,
453 JScript_GetScriptThreadID,
454 JScript_GetScriptThreadState,
455 JScript_InterruptScriptThread,
459 #define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
461 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
463 JScript *This = ASPARSE_THIS(iface);
464 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
467 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
469 JScript *This = ASPARSE_THIS(iface);
470 return IActiveScript_AddRef(ACTSCRIPT(This));
473 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
475 JScript *This = ASPARSE_THIS(iface);
476 return IActiveScript_Release(ACTSCRIPT(This));
479 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
481 JScript *This = ASPARSE_THIS(iface);
484 TRACE("(%p)\n", This);
489 ctx = heap_alloc_zero(sizeof(script_ctx_t));
491 return E_OUTOFMEMORY;
494 ctx->state = SCRIPTSTATE_UNINITIALIZED;
496 ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
505 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
506 LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
507 LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
508 DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
509 BSTR *pbstrName, EXCEPINFO *pexcepinfo)
511 JScript *This = ASPARSE_THIS(iface);
512 FIXME("(%p)->(%s %s %s %s %s %s %x %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
513 debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
514 debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), dwSourceContextCookie,
515 ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
519 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
520 LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
521 LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLine,
522 DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
524 JScript *This = ASPARSE_THIS(iface);
525 parser_ctx_t *parser_ctx;
528 TRACE("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode),
529 debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
530 dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo);
532 if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
535 hres = script_parse(This->ctx, pstrCode, &parser_ctx);
539 if(!is_started(This->ctx)) {
541 This->queue_tail = This->queue_tail->next = parser_ctx;
543 This->queue_head = This->queue_tail = parser_ctx;
547 hres = exec_global_code(This, parser_ctx);
548 parser_release(parser_ctx);
555 static const IActiveScriptParseVtbl JScriptParseVtbl = {
556 JScriptParse_QueryInterface,
558 JScriptParse_Release,
559 JScriptParse_InitNew,
560 JScriptParse_AddScriptlet,
561 JScriptParse_ParseScriptText
564 #define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
566 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
568 JScript *This = ASPARSEPROC_THIS(iface);
569 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
572 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
574 JScript *This = ASPARSEPROC_THIS(iface);
575 return IActiveScript_AddRef(ACTSCRIPT(This));
578 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
580 JScript *This = ASPARSEPROC_THIS(iface);
581 return IActiveScript_Release(ACTSCRIPT(This));
584 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
585 LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
586 LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
587 DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
589 JScript *This = ASPARSEPROC_THIS(iface);
590 FIXME("(%p)->()\n", This);
594 #undef ASPARSEPROC_THIS
596 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
597 JScriptParseProcedure_QueryInterface,
598 JScriptParseProcedure_AddRef,
599 JScriptParseProcedure_Release,
600 JScriptParseProcedure_ParseProcedureText,
603 #define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
605 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
607 JScript *This = ACTSCPPROP_THIS(iface);
608 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
611 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
613 JScript *This = ACTSCPPROP_THIS(iface);
614 return IActiveScript_AddRef(ACTSCRIPT(This));
617 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
619 JScript *This = ACTSCPPROP_THIS(iface);
620 return IActiveScript_Release(ACTSCRIPT(This));
623 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
624 VARIANT *pvarIndex, VARIANT *pvarValue)
626 JScript *This = ACTSCPPROP_THIS(iface);
627 FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
631 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
632 VARIANT *pvarIndex, VARIANT *pvarValue)
634 JScript *This = ACTSCPPROP_THIS(iface);
635 FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
639 #undef ACTSCPPROP_THIS
641 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
642 JScriptProperty_QueryInterface,
643 JScriptProperty_AddRef,
644 JScriptProperty_Release,
645 JScriptProperty_GetProperty,
646 JScriptProperty_SetProperty
649 #define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
651 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
653 JScript *This = OBJSAFETY_THIS(iface);
654 return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
657 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
659 JScript *This = OBJSAFETY_THIS(iface);
660 return IActiveScript_AddRef(ACTSCRIPT(This));
663 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
665 JScript *This = OBJSAFETY_THIS(iface);
666 return IActiveScript_Release(ACTSCRIPT(This));
669 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
671 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
672 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
674 JScript *This = OBJSAFETY_THIS(iface);
676 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
678 if(!pdwSupportedOptions || !pdwEnabledOptions)
681 *pdwSupportedOptions = SUPPORTED_OPTIONS;
682 *pdwEnabledOptions = This->safeopt;
687 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
688 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
690 JScript *This = OBJSAFETY_THIS(iface);
692 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
694 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
697 This->safeopt = dwEnabledOptions & dwEnabledOptions;
701 #undef OBJSAFETY_THIS
703 static const IObjectSafetyVtbl JScriptSafetyVtbl = {
704 JScriptSafety_QueryInterface,
705 JScriptSafety_AddRef,
706 JScriptSafety_Release,
707 JScriptSafety_GetInterfaceSafetyOptions,
708 JScriptSafety_SetInterfaceSafetyOptions
711 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
712 REFIID riid, void **ppv)
717 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
721 ret = heap_alloc_zero(sizeof(*ret));
723 ret->lpIActiveScriptVtbl = &JScriptVtbl;
724 ret->lpIActiveScriptParseVtbl = &JScriptParseVtbl;
725 ret->lpIActiveScriptParseProcedure2Vtbl = &JScriptParseProcedureVtbl;
726 ret->lpIActiveScriptPropertyVtbl = &JScriptPropertyVtbl;
727 ret->lpIObjectSafetyVtbl = &JScriptSafetyVtbl;
729 ret->safeopt = INTERFACE_USES_DISPEX;
731 hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
732 IActiveScript_Release(ACTSCRIPT(ret));