jscript: Added IActiveScript::GetScriptDispatch implementation.
[wine] / dlls / jscript / jscript.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 "jscript.h"
20 #include "objsafe.h"
21
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
25
26 typedef struct {
27     const IActiveScriptVtbl                 *lpIActiveScriptVtbl;
28     const IActiveScriptParseVtbl            *lpIActiveScriptParseVtbl;
29     const IActiveScriptParseProcedure2Vtbl  *lpIActiveScriptParseProcedure2Vtbl;
30     const IActiveScriptPropertyVtbl         *lpIActiveScriptPropertyVtbl;
31     const IObjectSafetyVtbl                 *lpIObjectSafetyVtbl;
32
33     LONG ref;
34
35     DWORD safeopt;
36     script_ctx_t *ctx;
37     LONG thread_id;
38
39     IActiveScriptSite *site;
40 } JScript;
41
42 #define ACTSCRIPT(x)    ((IActiveScript*)                 &(x)->lpIActiveScriptVtbl)
43 #define ASPARSE(x)      ((IActiveScriptParse*)            &(x)->lpIActiveScriptParseVtbl)
44 #define ASPARSEPROC(x)  ((IActiveScriptParseProcedure2*)  &(x)->lpIActiveScriptParseProcedure2Vtbl)
45 #define ACTSCPPROP(x)   ((IActiveScriptProperty*)         &(x)->lpIActiveScriptPropertyVtbl)
46 #define OBJSAFETY(x)    ((IObjectSafety*)                 &(x)->lpIObjectSafetyVtbl)
47
48 void script_release(script_ctx_t *ctx)
49 {
50     if(--ctx->ref)
51         return;
52
53     heap_free(ctx);
54 }
55
56 static void change_state(JScript *This, SCRIPTSTATE state)
57 {
58     if(This->ctx->state == state)
59         return;
60
61     This->ctx->state = state;
62     IActiveScriptSite_OnStateChange(This->site, state);
63 }
64
65 #define ACTSCRIPT_THIS(iface) DEFINE_THIS(JScript, IActiveScript, iface)
66
67 static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
68 {
69     JScript *This = ACTSCRIPT_THIS(iface);
70
71     *ppv = NULL;
72
73     if(IsEqualGUID(riid, &IID_IUnknown)) {
74         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
75         *ppv = ACTSCRIPT(This);
76     }else if(IsEqualGUID(riid, &IID_IActiveScript)) {
77         TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv);
78         *ppv = ACTSCRIPT(This);
79     }else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) {
80         TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv);
81         *ppv = ASPARSE(This);
82     }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure)) {
83         TRACE("(%p)->(IID_IActiveScriptParseProcedure %p)\n", This, ppv);
84         *ppv = ASPARSEPROC(This);
85     }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure2)) {
86         TRACE("(%p)->(IID_IActiveScriptParseProcedure2 %p)\n", This, ppv);
87         *ppv = ASPARSEPROC(This);
88     }else if(IsEqualGUID(riid, &IID_IActiveScriptProperty)) {
89         TRACE("(%p)->(IID_IActiveScriptProperty %p)\n", This, ppv);
90         *ppv = ACTSCPPROP(This);
91     }else if(IsEqualGUID(riid, &IID_IObjectSafety)) {
92         TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
93         *ppv = OBJSAFETY(This);
94     }
95
96     if(*ppv) {
97         IUnknown_AddRef((IUnknown*)*ppv);
98         return S_OK;
99     }
100
101     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
102     return E_NOINTERFACE;
103 }
104
105 static ULONG WINAPI JScript_AddRef(IActiveScript *iface)
106 {
107     JScript *This = ACTSCRIPT_THIS(iface);
108     LONG ref = InterlockedIncrement(&This->ref);
109
110     TRACE("(%p) ref=%d\n", This, ref);
111
112     return ref;
113 }
114
115 static ULONG WINAPI JScript_Release(IActiveScript *iface)
116 {
117     JScript *This = ACTSCRIPT_THIS(iface);
118     LONG ref = InterlockedDecrement(&This->ref);
119
120     TRACE("(%p) ref=%d\n", iface, ref);
121
122     if(!ref) {
123         if(This->ctx && This->ctx->state != SCRIPTSTATE_CLOSED)
124             IActiveScript_Close(ACTSCRIPT(This));
125         if(This->ctx)
126             script_release(This->ctx);
127         heap_free(This);
128         unlock_module();
129     }
130
131     return ref;
132 }
133
134 static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
135                                             IActiveScriptSite *pass)
136 {
137     JScript *This = ACTSCRIPT_THIS(iface);
138     LCID lcid;
139     HRESULT hres;
140
141     TRACE("(%p)->(%p)\n", This, pass);
142
143     if(!pass)
144         return E_POINTER;
145
146     if(This->site)
147         return E_UNEXPECTED;
148
149     if(!This->ctx) {
150         hres = IActiveScriptParse_InitNew(ASPARSE(This));
151         if(FAILED(hres))
152             return hres;
153     }
154
155     hres = create_dispex(This->ctx, &This->ctx->script_disp);
156     if(FAILED(hres))
157         return hres;
158
159     if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
160         return E_UNEXPECTED;
161
162     This->site = pass;
163     IActiveScriptSite_AddRef(This->site);
164
165     hres = IActiveScriptSite_GetLCID(This->site, &lcid);
166     if(hres == S_OK)
167         This->ctx->lcid = lcid;
168
169     change_state(This, SCRIPTSTATE_INITIALIZED);
170     return S_OK;
171 }
172
173 static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid,
174                                             void **ppvObject)
175 {
176     JScript *This = ACTSCRIPT_THIS(iface);
177     FIXME("(%p)->()\n", This);
178     return E_NOTIMPL;
179 }
180
181 static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
182 {
183     JScript *This = ACTSCRIPT_THIS(iface);
184     FIXME("(%p)->(%d)\n", This, ss);
185     return E_NOTIMPL;
186 }
187
188 static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
189 {
190     JScript *This = ACTSCRIPT_THIS(iface);
191     FIXME("(%p)->(%p)\n", This, pssState);
192     return E_NOTIMPL;
193 }
194
195 static HRESULT WINAPI JScript_Close(IActiveScript *iface)
196 {
197     JScript *This = ACTSCRIPT_THIS(iface);
198
199     TRACE("(%p)->()\n", This);
200
201     if(This->thread_id != GetCurrentThreadId())
202         return E_UNEXPECTED;
203
204     if(This->ctx) {
205         change_state(This, SCRIPTSTATE_CLOSED);
206
207         if(This->ctx->script_disp) {
208             IDispatchEx_Release(_IDispatchEx_(This->ctx->script_disp));
209             This->ctx->script_disp = NULL;
210         }
211     }
212
213     if(This->site) {
214         IActiveScriptSite_Release(This->site);
215         This->site = NULL;
216     }
217
218     return S_OK;
219 }
220
221 static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
222                                            LPCOLESTR pstrName, DWORD dwFlags)
223 {
224     JScript *This = ACTSCRIPT_THIS(iface);
225     FIXME("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
230                                          DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
231 {
232     JScript *This = ACTSCRIPT_THIS(iface);
233     FIXME("(%p)->()\n", This);
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
238                                                 IDispatch **ppdisp)
239 {
240     JScript *This = ACTSCRIPT_THIS(iface);
241
242     TRACE("(%p)->(%p)\n", This, ppdisp);
243
244     if(!ppdisp)
245         return E_POINTER;
246
247     if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) {
248         *ppdisp = NULL;
249         return E_UNEXPECTED;
250     }
251
252     *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp);
253     IDispatch_AddRef(*ppdisp);
254     return S_OK;
255 }
256
257 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
258                                                        SCRIPTTHREADID *pstridThread)
259 {
260     JScript *This = ACTSCRIPT_THIS(iface);
261     FIXME("(%p)->()\n", This);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
266                                                 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
267 {
268     JScript *This = ACTSCRIPT_THIS(iface);
269     FIXME("(%p)->()\n", This);
270     return E_NOTIMPL;
271 }
272
273 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
274         SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
275 {
276     JScript *This = ACTSCRIPT_THIS(iface);
277     FIXME("(%p)->()\n", This);
278     return E_NOTIMPL;
279 }
280
281 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
282         SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
283 {
284     JScript *This = ACTSCRIPT_THIS(iface);
285     FIXME("(%p)->()\n", This);
286     return E_NOTIMPL;
287 }
288
289 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
290 {
291     JScript *This = ACTSCRIPT_THIS(iface);
292     FIXME("(%p)->()\n", This);
293     return E_NOTIMPL;
294 }
295
296 #undef ACTSCRIPT_THIS
297
298 static const IActiveScriptVtbl JScriptVtbl = {
299     JScript_QueryInterface,
300     JScript_AddRef,
301     JScript_Release,
302     JScript_SetScriptSite,
303     JScript_GetScriptSite,
304     JScript_SetScriptState,
305     JScript_GetScriptState,
306     JScript_Close,
307     JScript_AddNamedItem,
308     JScript_AddTypeLib,
309     JScript_GetScriptDispatch,
310     JScript_GetCurrentScriptThreadID,
311     JScript_GetScriptThreadID,
312     JScript_GetScriptThreadState,
313     JScript_InterruptScriptThread,
314     JScript_Clone
315 };
316
317 #define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
318
319 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
320 {
321     JScript *This = ASPARSE_THIS(iface);
322     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
323 }
324
325 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
326 {
327     JScript *This = ASPARSE_THIS(iface);
328     return IActiveScript_AddRef(ACTSCRIPT(This));
329 }
330
331 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
332 {
333     JScript *This = ASPARSE_THIS(iface);
334     return IActiveScript_Release(ACTSCRIPT(This));
335 }
336
337 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
338 {
339     JScript *This = ASPARSE_THIS(iface);
340     script_ctx_t *ctx;
341
342     TRACE("(%p)\n", This);
343
344     if(This->ctx)
345         return E_UNEXPECTED;
346
347     ctx = heap_alloc_zero(sizeof(script_ctx_t));
348     if(!ctx)
349         return E_OUTOFMEMORY;
350
351     ctx->ref = 1;
352     ctx->state = SCRIPTSTATE_UNINITIALIZED;
353
354     ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
355     if(ctx) {
356         script_release(ctx);
357         return E_UNEXPECTED;
358     }
359
360     return S_OK;
361 }
362
363 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
364         LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
365         LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
366         DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
367         BSTR *pbstrName, EXCEPINFO *pexcepinfo)
368 {
369     JScript *This = ASPARSE_THIS(iface);
370     FIXME("(%p)->(%s %s %s %s %s %s %x %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
371           debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
372           debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), dwSourceContextCookie,
373           ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
374     return E_NOTIMPL;
375 }
376
377 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
378         LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
379         LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLine,
380         DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
381 {
382     JScript *This = ASPARSE_THIS(iface);
383     FIXME("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode),
384           debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
385           dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo);
386     return E_NOTIMPL;
387 }
388
389 #undef ASPARSE_THIS
390
391 static const IActiveScriptParseVtbl JScriptParseVtbl = {
392     JScriptParse_QueryInterface,
393     JScriptParse_AddRef,
394     JScriptParse_Release,
395     JScriptParse_InitNew,
396     JScriptParse_AddScriptlet,
397     JScriptParse_ParseScriptText
398 };
399
400 #define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
401
402 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
403 {
404     JScript *This = ASPARSEPROC_THIS(iface);
405     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
406 }
407
408 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
409 {
410     JScript *This = ASPARSEPROC_THIS(iface);
411     return IActiveScript_AddRef(ACTSCRIPT(This));
412 }
413
414 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
415 {
416     JScript *This = ASPARSEPROC_THIS(iface);
417     return IActiveScript_Release(ACTSCRIPT(This));
418 }
419
420 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
421         LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
422         LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
423         DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
424 {
425     JScript *This = ASPARSEPROC_THIS(iface);
426     FIXME("(%p)->()\n", This);
427     return E_NOTIMPL;
428 }
429
430 #undef ASPARSEPROC_THIS
431
432 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
433     JScriptParseProcedure_QueryInterface,
434     JScriptParseProcedure_AddRef,
435     JScriptParseProcedure_Release,
436     JScriptParseProcedure_ParseProcedureText,
437 };
438
439 #define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
440
441 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
442 {
443     JScript *This = ACTSCPPROP_THIS(iface);
444     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
445 }
446
447 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
448 {
449     JScript *This = ACTSCPPROP_THIS(iface);
450     return IActiveScript_AddRef(ACTSCRIPT(This));
451 }
452
453 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
454 {
455     JScript *This = ACTSCPPROP_THIS(iface);
456     return IActiveScript_Release(ACTSCRIPT(This));
457 }
458
459 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
460         VARIANT *pvarIndex, VARIANT *pvarValue)
461 {
462     JScript *This = ACTSCPPROP_THIS(iface);
463     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
464     return E_NOTIMPL;
465 }
466
467 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
468         VARIANT *pvarIndex, VARIANT *pvarValue)
469 {
470     JScript *This = ACTSCPPROP_THIS(iface);
471     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
472     return E_NOTIMPL;
473 }
474
475 #undef ACTSCPPROP_THIS
476
477 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
478     JScriptProperty_QueryInterface,
479     JScriptProperty_AddRef,
480     JScriptProperty_Release,
481     JScriptProperty_GetProperty,
482     JScriptProperty_SetProperty
483 };
484
485 #define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
486
487 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
488 {
489     JScript *This = OBJSAFETY_THIS(iface);
490     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
491 }
492
493 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
494 {
495     JScript *This = OBJSAFETY_THIS(iface);
496     return IActiveScript_AddRef(ACTSCRIPT(This));
497 }
498
499 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
500 {
501     JScript *This = OBJSAFETY_THIS(iface);
502     return IActiveScript_Release(ACTSCRIPT(This));
503 }
504
505 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
506
507 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
508         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
509 {
510     JScript *This = OBJSAFETY_THIS(iface);
511
512     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
513
514     if(!pdwSupportedOptions || !pdwEnabledOptions)
515         return E_POINTER;
516
517     *pdwSupportedOptions = SUPPORTED_OPTIONS;
518     *pdwEnabledOptions = This->safeopt;
519
520     return S_OK;
521 }
522
523 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
524         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
525 {
526     JScript *This = OBJSAFETY_THIS(iface);
527
528     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
529
530     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
531         return E_FAIL;
532
533     This->safeopt = dwEnabledOptions & dwEnabledOptions;
534     return S_OK;
535 }
536
537 #undef OBJSAFETY_THIS
538
539 static const IObjectSafetyVtbl JScriptSafetyVtbl = {
540     JScriptSafety_QueryInterface,
541     JScriptSafety_AddRef,
542     JScriptSafety_Release,
543     JScriptSafety_GetInterfaceSafetyOptions,
544     JScriptSafety_SetInterfaceSafetyOptions
545 };
546
547 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
548                                              REFIID riid, void **ppv)
549 {
550     JScript *ret;
551     HRESULT hres;
552
553     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
554
555     lock_module();
556
557     ret = heap_alloc_zero(sizeof(*ret));
558
559     ret->lpIActiveScriptVtbl                 = &JScriptVtbl;
560     ret->lpIActiveScriptParseVtbl            = &JScriptParseVtbl;
561     ret->lpIActiveScriptParseProcedure2Vtbl  = &JScriptParseProcedureVtbl;
562     ret->lpIActiveScriptPropertyVtbl         = &JScriptPropertyVtbl;
563     ret->lpIObjectSafetyVtbl                 = &JScriptSafetyVtbl;
564     ret->ref = 1;
565     ret->safeopt = INTERFACE_USES_DISPEX;
566
567     hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
568     IActiveScript_Release(ACTSCRIPT(ret));
569     return hres;
570 }