jscript: Added IActiveScript::Close 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     if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
156         return E_UNEXPECTED;
157
158     This->site = pass;
159     IActiveScriptSite_AddRef(This->site);
160
161     hres = IActiveScriptSite_GetLCID(This->site, &lcid);
162     if(hres == S_OK)
163         This->ctx->lcid = lcid;
164
165     change_state(This, SCRIPTSTATE_INITIALIZED);
166     return S_OK;
167 }
168
169 static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid,
170                                             void **ppvObject)
171 {
172     JScript *This = ACTSCRIPT_THIS(iface);
173     FIXME("(%p)->()\n", This);
174     return E_NOTIMPL;
175 }
176
177 static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
178 {
179     JScript *This = ACTSCRIPT_THIS(iface);
180     FIXME("(%p)->(%d)\n", This, ss);
181     return E_NOTIMPL;
182 }
183
184 static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
185 {
186     JScript *This = ACTSCRIPT_THIS(iface);
187     FIXME("(%p)->(%p)\n", This, pssState);
188     return E_NOTIMPL;
189 }
190
191 static HRESULT WINAPI JScript_Close(IActiveScript *iface)
192 {
193     JScript *This = ACTSCRIPT_THIS(iface);
194
195     TRACE("(%p)->()\n", This);
196
197     if(This->thread_id != GetCurrentThreadId())
198         return E_UNEXPECTED;
199
200     if(This->ctx)
201         change_state(This, SCRIPTSTATE_CLOSED);
202
203     if(This->site) {
204         IActiveScriptSite_Release(This->site);
205         This->site = NULL;
206     }
207
208     return S_OK;
209 }
210
211 static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
212                                            LPCOLESTR pstrName, DWORD dwFlags)
213 {
214     JScript *This = ACTSCRIPT_THIS(iface);
215     FIXME("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
216     return E_NOTIMPL;
217 }
218
219 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
220                                          DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
221 {
222     JScript *This = ACTSCRIPT_THIS(iface);
223     FIXME("(%p)->()\n", This);
224     return E_NOTIMPL;
225 }
226
227 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
228                                                 IDispatch **ppdisp)
229 {
230     JScript *This = ACTSCRIPT_THIS(iface);
231     FIXME("(%p)->()\n", This);
232     return E_NOTIMPL;
233 }
234
235 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
236                                                        SCRIPTTHREADID *pstridThread)
237 {
238     JScript *This = ACTSCRIPT_THIS(iface);
239     FIXME("(%p)->()\n", This);
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
244                                                 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
245 {
246     JScript *This = ACTSCRIPT_THIS(iface);
247     FIXME("(%p)->()\n", This);
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
252         SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
253 {
254     JScript *This = ACTSCRIPT_THIS(iface);
255     FIXME("(%p)->()\n", This);
256     return E_NOTIMPL;
257 }
258
259 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
260         SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
261 {
262     JScript *This = ACTSCRIPT_THIS(iface);
263     FIXME("(%p)->()\n", This);
264     return E_NOTIMPL;
265 }
266
267 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
268 {
269     JScript *This = ACTSCRIPT_THIS(iface);
270     FIXME("(%p)->()\n", This);
271     return E_NOTIMPL;
272 }
273
274 #undef ACTSCRIPT_THIS
275
276 static const IActiveScriptVtbl JScriptVtbl = {
277     JScript_QueryInterface,
278     JScript_AddRef,
279     JScript_Release,
280     JScript_SetScriptSite,
281     JScript_GetScriptSite,
282     JScript_SetScriptState,
283     JScript_GetScriptState,
284     JScript_Close,
285     JScript_AddNamedItem,
286     JScript_AddTypeLib,
287     JScript_GetScriptDispatch,
288     JScript_GetCurrentScriptThreadID,
289     JScript_GetScriptThreadID,
290     JScript_GetScriptThreadState,
291     JScript_InterruptScriptThread,
292     JScript_Clone
293 };
294
295 #define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
296
297 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
298 {
299     JScript *This = ASPARSE_THIS(iface);
300     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
301 }
302
303 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
304 {
305     JScript *This = ASPARSE_THIS(iface);
306     return IActiveScript_AddRef(ACTSCRIPT(This));
307 }
308
309 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
310 {
311     JScript *This = ASPARSE_THIS(iface);
312     return IActiveScript_Release(ACTSCRIPT(This));
313 }
314
315 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
316 {
317     JScript *This = ASPARSE_THIS(iface);
318     script_ctx_t *ctx;
319
320     TRACE("(%p)\n", This);
321
322     if(This->ctx)
323         return E_UNEXPECTED;
324
325     ctx = heap_alloc_zero(sizeof(script_ctx_t));
326     if(!ctx)
327         return E_OUTOFMEMORY;
328
329     ctx->ref = 1;
330     ctx->state = SCRIPTSTATE_UNINITIALIZED;
331
332     ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
333     if(ctx) {
334         script_release(ctx);
335         return E_UNEXPECTED;
336     }
337
338     return S_OK;
339 }
340
341 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
342         LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
343         LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
344         DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
345         BSTR *pbstrName, EXCEPINFO *pexcepinfo)
346 {
347     JScript *This = ASPARSE_THIS(iface);
348     FIXME("(%p)->(%s %s %s %s %s %s %x %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
349           debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
350           debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), dwSourceContextCookie,
351           ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
352     return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
356         LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
357         LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLine,
358         DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
359 {
360     JScript *This = ASPARSE_THIS(iface);
361     FIXME("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode),
362           debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
363           dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo);
364     return E_NOTIMPL;
365 }
366
367 #undef ASPARSE_THIS
368
369 static const IActiveScriptParseVtbl JScriptParseVtbl = {
370     JScriptParse_QueryInterface,
371     JScriptParse_AddRef,
372     JScriptParse_Release,
373     JScriptParse_InitNew,
374     JScriptParse_AddScriptlet,
375     JScriptParse_ParseScriptText
376 };
377
378 #define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
379
380 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
381 {
382     JScript *This = ASPARSEPROC_THIS(iface);
383     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
384 }
385
386 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
387 {
388     JScript *This = ASPARSEPROC_THIS(iface);
389     return IActiveScript_AddRef(ACTSCRIPT(This));
390 }
391
392 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
393 {
394     JScript *This = ASPARSEPROC_THIS(iface);
395     return IActiveScript_Release(ACTSCRIPT(This));
396 }
397
398 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
399         LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
400         LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
401         DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
402 {
403     JScript *This = ASPARSEPROC_THIS(iface);
404     FIXME("(%p)->()\n", This);
405     return E_NOTIMPL;
406 }
407
408 #undef ASPARSEPROC_THIS
409
410 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
411     JScriptParseProcedure_QueryInterface,
412     JScriptParseProcedure_AddRef,
413     JScriptParseProcedure_Release,
414     JScriptParseProcedure_ParseProcedureText,
415 };
416
417 #define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
418
419 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
420 {
421     JScript *This = ACTSCPPROP_THIS(iface);
422     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
423 }
424
425 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
426 {
427     JScript *This = ACTSCPPROP_THIS(iface);
428     return IActiveScript_AddRef(ACTSCRIPT(This));
429 }
430
431 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
432 {
433     JScript *This = ACTSCPPROP_THIS(iface);
434     return IActiveScript_Release(ACTSCRIPT(This));
435 }
436
437 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
438         VARIANT *pvarIndex, VARIANT *pvarValue)
439 {
440     JScript *This = ACTSCPPROP_THIS(iface);
441     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
442     return E_NOTIMPL;
443 }
444
445 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
446         VARIANT *pvarIndex, VARIANT *pvarValue)
447 {
448     JScript *This = ACTSCPPROP_THIS(iface);
449     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
450     return E_NOTIMPL;
451 }
452
453 #undef ACTSCPPROP_THIS
454
455 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
456     JScriptProperty_QueryInterface,
457     JScriptProperty_AddRef,
458     JScriptProperty_Release,
459     JScriptProperty_GetProperty,
460     JScriptProperty_SetProperty
461 };
462
463 #define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
464
465 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
466 {
467     JScript *This = OBJSAFETY_THIS(iface);
468     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
469 }
470
471 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
472 {
473     JScript *This = OBJSAFETY_THIS(iface);
474     return IActiveScript_AddRef(ACTSCRIPT(This));
475 }
476
477 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
478 {
479     JScript *This = OBJSAFETY_THIS(iface);
480     return IActiveScript_Release(ACTSCRIPT(This));
481 }
482
483 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
484
485 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
486         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
487 {
488     JScript *This = OBJSAFETY_THIS(iface);
489
490     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
491
492     if(!pdwSupportedOptions || !pdwEnabledOptions)
493         return E_POINTER;
494
495     *pdwSupportedOptions = SUPPORTED_OPTIONS;
496     *pdwEnabledOptions = This->safeopt;
497
498     return S_OK;
499 }
500
501 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
502         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
503 {
504     JScript *This = OBJSAFETY_THIS(iface);
505
506     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
507
508     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
509         return E_FAIL;
510
511     This->safeopt = dwEnabledOptions & dwEnabledOptions;
512     return S_OK;
513 }
514
515 #undef OBJSAFETY_THIS
516
517 static const IObjectSafetyVtbl JScriptSafetyVtbl = {
518     JScriptSafety_QueryInterface,
519     JScriptSafety_AddRef,
520     JScriptSafety_Release,
521     JScriptSafety_GetInterfaceSafetyOptions,
522     JScriptSafety_SetInterfaceSafetyOptions
523 };
524
525 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
526                                              REFIID riid, void **ppv)
527 {
528     JScript *ret;
529     HRESULT hres;
530
531     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
532
533     lock_module();
534
535     ret = heap_alloc_zero(sizeof(*ret));
536
537     ret->lpIActiveScriptVtbl                 = &JScriptVtbl;
538     ret->lpIActiveScriptParseVtbl            = &JScriptParseVtbl;
539     ret->lpIActiveScriptParseProcedure2Vtbl  = &JScriptParseProcedureVtbl;
540     ret->lpIActiveScriptPropertyVtbl         = &JScriptPropertyVtbl;
541     ret->lpIObjectSafetyVtbl                 = &JScriptSafetyVtbl;
542     ret->ref = 1;
543     ret->safeopt = INTERFACE_USES_DISPEX;
544
545     hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
546     IActiveScript_Release(ACTSCRIPT(ret));
547     return hres;
548 }