mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / scrobj / scrobj.c
blob48943d235ec9fd485c8dff0c5226251208ec4826
1 /*
2 * Copyright 2017 Nikolay Sivov
3 * Copyright 2019 Jacek Caban for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "ole2.h"
26 #include "olectl.h"
27 #include "rpcproxy.h"
28 #include "activscp.h"
29 #include "dispex.h"
30 #include "mshtmhst.h"
32 #include "initguid.h"
33 #include "scrobj.h"
34 #include "xmllite.h"
36 #include "wine/debug.h"
37 #include "wine/heap.h"
38 #include "wine/list.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(scrobj);
42 #ifdef _WIN64
44 #define IActiveScriptParse_Release IActiveScriptParse64_Release
45 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
46 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
48 #else
50 #define IActiveScriptParse_Release IActiveScriptParse32_Release
51 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
52 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
54 #endif
56 static HINSTANCE scrobj_instance;
58 enum member_type
60 MEMBER_METHOD,
61 MEMBER_PROPERTY
64 #define PROP_GETTER 0x01
65 #define PROP_SETTER 0x02
67 struct scriptlet_member
69 struct list entry;
70 enum member_type type;
71 WCHAR *name;
72 union
74 struct list parameters;
75 unsigned int flags;
76 } u;
79 struct method_parameter
81 struct list entry;
82 WCHAR *name;
85 struct scriptlet_script
87 struct list entry;
88 WCHAR *language;
89 WCHAR *body;
92 struct scriptlet_global
94 IDispatchEx IDispatchEx_iface;
95 LONG ref;
98 struct scriptlet_factory
100 IClassFactory IClassFactory_iface;
102 LONG ref;
104 IXmlReader *xml_reader;
105 IMoniker *moniker;
107 BOOL have_registration;
108 BOOL have_public;
109 WCHAR *description;
110 WCHAR *progid;
111 WCHAR *versioned_progid;
112 WCHAR *version;
113 WCHAR *classid_str;
114 CLSID classid;
116 struct list hosts;
117 struct list members;
118 struct list scripts;
121 struct script_reference
123 struct script_host *host;
124 DISPID id;
127 struct object_member
129 enum member_type type;
130 BSTR name;
131 union
133 struct script_reference method;
134 struct
136 struct script_reference get;
137 struct script_reference put;
138 } property;
139 } u;
142 struct scriptlet_instance
144 IDispatchEx IDispatchEx_iface;
145 LONG ref;
146 struct list hosts;
147 struct scriptlet_global *global;
148 unsigned member_cnt;
149 struct object_member *members;
152 struct script_host
154 IActiveScriptSite IActiveScriptSite_iface;
155 IActiveScriptSiteWindow IActiveScriptSiteWindow_iface;
156 IServiceProvider IServiceProvider_iface;
158 LONG ref;
159 struct list entry;
161 WCHAR *language;
163 IActiveScript *active_script;
164 IActiveScriptParse *parser;
165 IDispatchEx *script_dispatch;
166 struct scriptlet_instance *object;
167 SCRIPTSTATE state;
168 BOOL cloned;
171 typedef enum tid_t
173 NULL_tid,
174 IGenScriptletTLib_tid,
175 LAST_tid
176 } tid_t;
178 static ITypeLib *typelib;
179 static ITypeInfo *typeinfos[LAST_tid];
181 static REFIID tid_ids[] = {
182 &IID_NULL,
183 &IID_IGenScriptletTLib,
186 static HRESULT load_typelib(void)
188 HRESULT hres;
189 ITypeLib *tl;
191 if (typelib)
192 return S_OK;
194 hres = LoadRegTypeLib(&LIBID_Scriptlet, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
195 if (FAILED(hres))
197 ERR("LoadRegTypeLib failed: %08x\n", hres);
198 return hres;
201 if (InterlockedCompareExchangePointer((void **)&typelib, tl, NULL))
202 ITypeLib_Release(tl);
203 return hres;
206 static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
208 HRESULT hres;
210 if (FAILED(hres = load_typelib()))
211 return hres;
213 if (!typeinfos[tid])
215 ITypeInfo *ti;
217 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
218 if (FAILED(hres)) {
219 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
220 return hres;
223 if (InterlockedCompareExchangePointer((void **)(typeinfos+tid), ti, NULL))
224 ITypeInfo_Release(ti);
227 *typeinfo = typeinfos[tid];
228 ITypeInfo_AddRef(typeinfos[tid]);
229 return S_OK;
232 static void release_typelib(void)
234 unsigned i;
236 if (!typelib)
237 return;
239 for (i = 0; i < ARRAY_SIZE(typeinfos); i++)
240 if (typeinfos[i])
241 ITypeInfo_Release(typeinfos[i]);
243 ITypeLib_Release(typelib);
246 static WCHAR *heap_strdupW(const WCHAR *str)
248 WCHAR *ret;
249 size_t size = (wcslen(str) + 1) * sizeof(WCHAR);
250 if (!(ret = heap_alloc(size))) return NULL;
251 memcpy(ret, str, size);
252 return ret;
255 static inline struct scriptlet_global *global_from_IDispatchEx(IDispatchEx *iface)
257 return CONTAINING_RECORD(iface, struct scriptlet_global, IDispatchEx_iface);
260 static HRESULT WINAPI global_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
262 struct scriptlet_global *This = global_from_IDispatchEx(iface);
264 if (IsEqualGUID(&IID_IUnknown, riid))
266 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
267 *ppv = &This->IDispatchEx_iface;
269 else if (IsEqualGUID(&IID_IDispatch, riid))
271 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
272 *ppv = &This->IDispatchEx_iface;
274 else if (IsEqualGUID(&IID_IDispatchEx, riid))
276 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
277 *ppv = &This->IDispatchEx_iface;
279 else
281 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
282 *ppv = NULL;
283 return E_NOINTERFACE;
286 IUnknown_AddRef((IUnknown*)*ppv);
287 return S_OK;
290 static ULONG WINAPI global_AddRef(IDispatchEx *iface)
292 struct scriptlet_global *This = global_from_IDispatchEx(iface);
293 ULONG ref = InterlockedIncrement(&This->ref);
295 TRACE("(%p) ref=%d\n", This, ref);
297 return ref;
300 static ULONG WINAPI global_Release(IDispatchEx *iface)
302 struct scriptlet_global *This = global_from_IDispatchEx(iface);
303 ULONG ref = InterlockedDecrement(&This->ref);
305 TRACE("(%p) ref=%d\n", This, ref);
307 if (!ref) heap_free(This);
308 return ref;
311 static HRESULT WINAPI global_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
313 struct scriptlet_global *This = global_from_IDispatchEx(iface);
314 FIXME("(%p)->(%p)\n", This, pctinfo);
315 return E_NOTIMPL;
318 static HRESULT WINAPI global_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
320 struct scriptlet_global *This = global_from_IDispatchEx(iface);
321 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
322 return E_NOTIMPL;
325 static HRESULT WINAPI global_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
326 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
328 struct scriptlet_global *This = global_from_IDispatchEx(iface);
329 UINT i;
330 HRESULT hres;
332 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
334 for(i=0; i < cNames; i++)
336 hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId + i);
337 if(FAILED(hres))
338 return hres;
341 return S_OK;
344 static HRESULT WINAPI global_Invoke(IDispatchEx *iface, DISPID dispIdMember,
345 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
346 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
348 struct scriptlet_global *This = global_from_IDispatchEx(iface);
349 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
350 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
351 return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags,
352 pDispParams, pVarResult, pExcepInfo, NULL);
355 static HRESULT WINAPI global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
357 struct scriptlet_global *This = global_from_IDispatchEx(iface);
358 FIXME("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
359 return E_NOTIMPL;
362 static HRESULT WINAPI global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
363 VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
365 struct scriptlet_global *This = global_from_IDispatchEx(iface);
366 FIXME("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
367 return E_NOTIMPL;
370 static HRESULT WINAPI global_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
372 struct scriptlet_global *This = global_from_IDispatchEx(iface);
373 FIXME("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
374 return E_NOTIMPL;
377 static HRESULT WINAPI global_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
379 struct scriptlet_global *This = global_from_IDispatchEx(iface);
380 FIXME("(%p)->(%x)\n", This, id);
381 return E_NOTIMPL;
384 static HRESULT WINAPI global_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
386 struct scriptlet_global *This = global_from_IDispatchEx(iface);
387 FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex);
388 return E_NOTIMPL;
391 static HRESULT WINAPI global_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
393 struct scriptlet_global *This = global_from_IDispatchEx(iface);
394 FIXME("(%p)->(%x %p)\n", This, id, pbstrName);
395 return E_NOTIMPL;
398 static HRESULT WINAPI global_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
400 struct scriptlet_global *This = global_from_IDispatchEx(iface);
401 FIXME("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
402 return E_NOTIMPL;
405 static HRESULT WINAPI global_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
407 struct scriptlet_global *This = global_from_IDispatchEx(iface);
408 FIXME("(%p)->(%p)\n", This, ppunk);
409 return E_NOTIMPL;
412 static IDispatchExVtbl global_vtbl = {
413 global_QueryInterface,
414 global_AddRef,
415 global_Release,
416 global_GetTypeInfoCount,
417 global_GetTypeInfo,
418 global_GetIDsOfNames,
419 global_Invoke,
420 global_GetDispID,
421 global_InvokeEx,
422 global_DeleteMemberByName,
423 global_DeleteMemberByDispID,
424 global_GetMemberProperties,
425 global_GetMemberName,
426 global_GetNextDispID,
427 global_GetNameSpaceParent
430 static HRESULT set_script_state(struct script_host *host, SCRIPTSTATE state)
432 HRESULT hres;
433 if (state == host->state) return S_OK;
434 hres = IActiveScript_SetScriptState(host->active_script, state);
435 if (FAILED(hres)) return hres;
436 host->state = state;
437 return S_OK;
440 static inline struct script_host *impl_from_IActiveScriptSite(IActiveScriptSite *iface)
442 return CONTAINING_RECORD(iface, struct script_host, IActiveScriptSite_iface);
445 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
447 struct script_host *This = impl_from_IActiveScriptSite(iface);
449 if (IsEqualGUID(&IID_IUnknown, riid))
451 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
452 *ppv = &This->IActiveScriptSite_iface;
454 else if (IsEqualGUID(&IID_IActiveScriptSite, riid))
456 TRACE("(%p)->(IID_IActiveScriptSite %p)\n", This, ppv);
457 *ppv = &This->IActiveScriptSite_iface;
459 else if (IsEqualGUID(&IID_IActiveScriptSiteWindow, riid))
461 TRACE("(%p)->(IID_IActiveScriptSiteWindow %p)\n", This, ppv);
462 *ppv = &This->IActiveScriptSiteWindow_iface;
464 else if(IsEqualGUID(&IID_IServiceProvider, riid))
466 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
467 *ppv = &This->IServiceProvider_iface;
469 else
471 WARN("(%p)->(%s %p) interface not supported\n", This, debugstr_guid(riid), ppv);
472 *ppv = NULL;
473 return E_NOINTERFACE;
476 IUnknown_AddRef((IUnknown*)*ppv);
477 return S_OK;
480 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
482 struct script_host *This = impl_from_IActiveScriptSite(iface);
483 LONG ref = InterlockedIncrement(&This->ref);
485 TRACE("(%p) ref=%d\n", This, ref);
487 return ref;
490 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
492 struct script_host *This = impl_from_IActiveScriptSite(iface);
493 LONG ref = InterlockedDecrement(&This->ref);
495 TRACE("(%p) ref=%d\n", This, ref);
497 if(!ref) {
498 heap_free(This->language);
499 heap_free(This);
502 return ref;
505 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *lcid)
507 struct script_host *This = impl_from_IActiveScriptSite(iface);
509 TRACE("(%p, %p)\n", This, lcid);
511 *lcid = GetUserDefaultLCID();
512 return S_OK;
515 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR name, DWORD mask,
516 IUnknown **unk, ITypeInfo **ti)
518 struct script_host *This = impl_from_IActiveScriptSite(iface);
520 TRACE("(%p, %s, %#x, %p, %p)\n", This, debugstr_w(name), mask, unk, ti);
522 if (mask != SCRIPTINFO_IUNKNOWN)
524 FIXME("mask %x not supported\n", mask);
525 return E_NOTIMPL;
528 if (wcscmp(name, L"scriptlet") && wcscmp(name, L"globals"))
530 FIXME("%s not supported\n", debugstr_w(name));
531 return E_FAIL;
534 if (!This->object) return E_UNEXPECTED;
536 *unk = (IUnknown *)&This->object->global->IDispatchEx_iface;
537 IUnknown_AddRef(*unk);
538 return S_OK;
541 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *version)
543 struct script_host *This = impl_from_IActiveScriptSite(iface);
544 FIXME("(%p, %p)\n", This, version);
545 return E_NOTIMPL;
548 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, const VARIANT *result,
549 const EXCEPINFO *ei)
551 struct script_host *This = impl_from_IActiveScriptSite(iface);
552 FIXME("(%p, %s, %p)\n", This, debugstr_variant(result), ei);
553 return E_NOTIMPL;
556 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE state)
558 struct script_host *This = impl_from_IActiveScriptSite(iface);
559 TRACE("(%p, %d)\n", This, state);
560 return E_NOTIMPL;
563 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *script_error)
565 struct script_host *This = impl_from_IActiveScriptSite(iface);
566 FIXME("(%p, %p)\n", This, script_error);
567 return E_NOTIMPL;
570 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
572 struct script_host *This = impl_from_IActiveScriptSite(iface);
573 TRACE("(%p)\n", This);
574 return S_OK;
577 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
579 struct script_host *This = impl_from_IActiveScriptSite(iface);
580 TRACE("(%p)\n", This);
581 return S_OK;
584 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
585 ActiveScriptSite_QueryInterface,
586 ActiveScriptSite_AddRef,
587 ActiveScriptSite_Release,
588 ActiveScriptSite_GetLCID,
589 ActiveScriptSite_GetItemInfo,
590 ActiveScriptSite_GetDocVersionString,
591 ActiveScriptSite_OnScriptTerminate,
592 ActiveScriptSite_OnStateChange,
593 ActiveScriptSite_OnScriptError,
594 ActiveScriptSite_OnEnterScript,
595 ActiveScriptSite_OnLeaveScript
598 static inline struct script_host *impl_from_IActiveScriptSiteWindow(IActiveScriptSiteWindow *iface)
600 return CONTAINING_RECORD(iface, struct script_host, IActiveScriptSiteWindow_iface);
603 static HRESULT WINAPI ActiveScriptSiteWindow_QueryInterface(IActiveScriptSiteWindow *iface, REFIID riid, void **obj)
605 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
606 return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, obj);
609 static ULONG WINAPI ActiveScriptSiteWindow_AddRef(IActiveScriptSiteWindow *iface)
611 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
612 return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
615 static ULONG WINAPI ActiveScriptSiteWindow_Release(IActiveScriptSiteWindow *iface)
617 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
618 return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
621 static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *iface, HWND *hwnd)
623 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
624 FIXME("(%p, %p)\n", This, hwnd);
625 return E_NOTIMPL;
628 static HRESULT WINAPI ActiveScriptSiteWindow_EnableModeless(IActiveScriptSiteWindow *iface, BOOL enable)
630 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
631 FIXME("(%p, %d)\n", This, enable);
632 return E_NOTIMPL;
635 static const IActiveScriptSiteWindowVtbl ActiveScriptSiteWindowVtbl = {
636 ActiveScriptSiteWindow_QueryInterface,
637 ActiveScriptSiteWindow_AddRef,
638 ActiveScriptSiteWindow_Release,
639 ActiveScriptSiteWindow_GetWindow,
640 ActiveScriptSiteWindow_EnableModeless
643 static inline struct script_host *impl_from_IServiceProvider(IServiceProvider *iface)
645 return CONTAINING_RECORD(iface, struct script_host, IServiceProvider_iface);
648 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **obj)
650 struct script_host *This = impl_from_IServiceProvider(iface);
651 return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, obj);
654 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
656 struct script_host *This = impl_from_IServiceProvider(iface);
657 return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
660 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
662 struct script_host *This = impl_from_IServiceProvider(iface);
663 return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
666 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID service,
667 REFIID riid, void **obj)
669 struct script_host *This = impl_from_IServiceProvider(iface);
670 FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(service), debugstr_guid(riid), obj);
671 return E_NOTIMPL;
674 static const IServiceProviderVtbl ServiceProviderVtbl = {
675 ServiceProvider_QueryInterface,
676 ServiceProvider_AddRef,
677 ServiceProvider_Release,
678 ServiceProvider_QueryService
681 static struct script_host *find_script_host(struct list *hosts, const WCHAR *language)
683 struct script_host *host;
684 LIST_FOR_EACH_ENTRY(host, hosts, struct script_host, entry)
686 if (!wcscmp(host->language, language)) return host;
688 return NULL;
691 static HRESULT parse_scripts(struct scriptlet_factory *factory, struct list *hosts, BOOL start)
693 DWORD parse_flags = SCRIPTTEXT_ISVISIBLE;
694 struct scriptlet_script *script;
695 struct script_host *host;
696 HRESULT hres;
698 if (!start) parse_flags |= SCRIPTITEM_ISPERSISTENT;
700 LIST_FOR_EACH_ENTRY(script, &factory->scripts, struct scriptlet_script, entry)
702 host = find_script_host(hosts, script->language);
704 if (start && host->state != SCRIPTSTATE_STARTED)
706 hres = set_script_state(host, SCRIPTSTATE_STARTED);
707 if (FAILED(hres)) return hres;
710 if (host->cloned) continue;
712 hres = IActiveScriptParse_ParseScriptText(host->parser, script->body, NULL, NULL, NULL, 0, 0 /* FIXME */,
713 parse_flags, NULL, NULL);
714 if (FAILED(hres))
716 WARN("ParseScriptText failed: %08x\n", hres);
717 return hres;
720 if (!start)
722 LIST_FOR_EACH_ENTRY(host, hosts, struct script_host, entry)
724 if (host->state != SCRIPTSTATE_UNINITIALIZED)
725 set_script_state(host, SCRIPTSTATE_UNINITIALIZED);
728 return S_OK;
731 static HRESULT lookup_script_properties(struct scriptlet_instance *object, BSTR name, struct script_reference *ret)
733 struct script_host *host;
734 HRESULT hres;
736 LIST_FOR_EACH_ENTRY(host, &object->hosts, struct script_host, entry)
738 hres = IDispatchEx_GetDispID(host->script_dispatch, name, 0, &ret->id);
739 if (FAILED(hres)) continue;
740 ret->host = host;
741 return S_OK;
744 FIXME("Could not find %s in scripts\n", debugstr_w(name));
745 return E_FAIL;
748 static HRESULT lookup_object_properties(struct scriptlet_instance *object, struct scriptlet_factory *factory)
750 struct scriptlet_member *member;
751 unsigned i = 0, member_cnt = 0;
752 size_t len;
753 BSTR name;
754 HRESULT hres;
756 LIST_FOR_EACH_ENTRY(member, &factory->members, struct scriptlet_member, entry)
757 member_cnt++;
759 if (!member_cnt) return S_OK;
761 if (!(object->members = heap_alloc_zero(member_cnt * sizeof(*object->members)))) return E_OUTOFMEMORY;
762 object->member_cnt = member_cnt;
764 LIST_FOR_EACH_ENTRY(member, &factory->members, struct scriptlet_member, entry)
766 object->members[i].type = member->type;
767 if (!(object->members[i].name = SysAllocString(member->name))) return E_OUTOFMEMORY;
768 switch (member->type)
770 case MEMBER_METHOD:
771 hres = lookup_script_properties(object, object->members[i].name, &object->members[i].u.method);
772 if (FAILED(hres)) return hres;
773 break;
774 case MEMBER_PROPERTY:
775 len = wcslen(member->name);
776 if (!(name = SysAllocStringLen(NULL, len + 4))) return E_OUTOFMEMORY;
777 wcscpy(name, L"get_");
778 wcscat(name, member->name);
779 hres = lookup_script_properties(object, name, &object->members[i].u.property.get);
780 if (SUCCEEDED(hres))
782 memcpy(name, L"put", 3 * sizeof(WCHAR));
783 hres = lookup_script_properties(object, name, &object->members[i].u.property.put);
785 SysFreeString(name);
786 if (FAILED(hres)) return hres;
787 break;
789 i++;
792 return S_OK;
795 static HRESULT init_script_host(struct script_host *host, IActiveScript *clone)
797 HRESULT hres;
799 if (!clone)
801 IClassFactoryEx *factory_ex;
802 IClassFactory *factory;
803 IUnknown *unk;
804 CLSID clsid;
806 if (FAILED(hres = CLSIDFromProgID(host->language, &clsid)))
808 WARN("Could not find script engine for %s\n", debugstr_w(host->language));
809 return hres;
812 hres = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, NULL,
813 &IID_IClassFactory, (void**)&factory);
814 if (FAILED(hres)) return hres;
816 hres = IClassFactory_QueryInterface(factory, &IID_IClassFactoryEx, (void**)&factory_ex);
817 if (SUCCEEDED(hres))
819 FIXME("Use IClassFactoryEx\n");
820 IClassFactoryEx_Release(factory_ex);
823 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IUnknown, (void**)&unk);
824 IClassFactory_Release(factory);
825 if (FAILED(hres)) return hres;
827 hres = IUnknown_QueryInterface(unk, &IID_IActiveScript, (void**)&host->active_script);
828 IUnknown_Release(unk);
829 if (FAILED(hres)) return hres;
831 else
833 IActiveScript_AddRef(clone);
834 host->active_script = clone;
835 host->cloned = TRUE;
838 hres = IActiveScript_QueryInterface(host->active_script, &IID_IActiveScriptParse, (void**)&host->parser);
839 if (FAILED(hres)) return hres;
841 if (!clone)
843 hres = IActiveScriptParse_InitNew(host->parser);
844 if (FAILED(hres))
846 IActiveScriptParse_Release(host->parser);
847 host->parser = NULL;
848 return hres;
852 return IActiveScript_SetScriptSite(host->active_script, &host->IActiveScriptSite_iface);
855 static HRESULT create_script_host(const WCHAR *language, IActiveScript *origin_script, struct list *hosts, struct script_host **ret)
857 IActiveScript *clone = NULL;
858 struct script_host *host;
859 HRESULT hres;
861 if (!(host = heap_alloc_zero(sizeof(*host)))) return E_OUTOFMEMORY;
863 host->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl;
864 host->IActiveScriptSiteWindow_iface.lpVtbl = &ActiveScriptSiteWindowVtbl;
865 host->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
866 host->ref = 1;
867 host->state = SCRIPTSTATE_CLOSED;
869 if (!(host->language = heap_strdupW(language)))
871 IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
872 return E_OUTOFMEMORY;
875 if (origin_script)
877 hres = IActiveScript_Clone(origin_script, &clone);
878 if (FAILED(hres)) clone = NULL;
881 list_add_tail(hosts, &host->entry);
882 hres = init_script_host(host, clone);
883 if (clone) IActiveScript_Release(clone);
884 if (FAILED(hres)) return hres;
885 if (ret) *ret = host;
886 return S_OK;
889 static void detach_script_hosts(struct list *hosts)
891 while (!list_empty(hosts))
893 struct script_host *host = LIST_ENTRY(list_head(hosts), struct script_host, entry);
894 if (host->state != SCRIPTSTATE_UNINITIALIZED) set_script_state(host, SCRIPTSTATE_UNINITIALIZED);
895 list_remove(&host->entry);
896 host->object = NULL;
897 if (host->script_dispatch)
899 IDispatchEx_Release(host->script_dispatch);
900 host->script_dispatch = NULL;
902 if (host->parser)
904 IActiveScript_Close(host->active_script);
905 IActiveScriptParse_Release(host->parser);
906 host->parser = NULL;
908 if (host->active_script)
910 IActiveScript_Release(host->active_script);
911 host->active_script = NULL;
913 IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
917 static HRESULT create_scriptlet_hosts(struct scriptlet_factory *factory, struct list *hosts)
919 struct scriptlet_script *script;
920 HRESULT hres;
922 LIST_FOR_EACH_ENTRY(script, &factory->scripts, struct scriptlet_script, entry)
924 if (find_script_host(hosts, script->language)) continue;
925 hres = create_script_host(script->language, NULL, hosts, NULL);
926 if (FAILED(hres))
928 detach_script_hosts(hosts);
929 return hres;
933 return S_OK;
936 static inline struct scriptlet_instance *impl_from_IDispatchEx(IDispatchEx *iface)
938 return CONTAINING_RECORD(iface, struct scriptlet_instance, IDispatchEx_iface);
941 static HRESULT WINAPI scriptlet_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
943 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
945 if (IsEqualGUID(&IID_IUnknown, riid))
947 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
948 *ppv = &This->IDispatchEx_iface;
950 else if (IsEqualGUID(&IID_IDispatch, riid))
952 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
953 *ppv = &This->IDispatchEx_iface;
955 else if (IsEqualGUID(&IID_IDispatchEx, riid))
957 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
958 *ppv = &This->IDispatchEx_iface;
960 else
962 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
963 *ppv = NULL;
964 return E_NOINTERFACE;
967 IUnknown_AddRef((IUnknown*)*ppv);
968 return S_OK;
971 static ULONG WINAPI scriptlet_AddRef(IDispatchEx *iface)
973 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
974 ULONG ref = InterlockedIncrement(&This->ref);
976 TRACE("(%p) ref=%d\n", This, ref);
978 return ref;
981 static ULONG WINAPI scriptlet_Release(IDispatchEx *iface)
983 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
984 ULONG ref = InterlockedDecrement(&This->ref);
986 TRACE("(%p) ref=%d\n", This, ref);
988 if (!ref)
990 unsigned i;
991 for (i = 0; i < This->member_cnt; i++)
992 SysFreeString(This->members[i].name);
993 heap_free(This->members);
994 detach_script_hosts(&This->hosts);
995 if (This->global) IDispatchEx_Release(&This->global->IDispatchEx_iface);
996 heap_free(This);
998 return ref;
1001 static HRESULT WINAPI scriptlet_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
1003 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1004 FIXME("(%p)->(%p)\n", This, pctinfo);
1005 return E_NOTIMPL;
1008 static HRESULT WINAPI scriptlet_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1010 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1011 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1012 return E_NOTIMPL;
1015 static HRESULT WINAPI scriptlet_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
1016 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1018 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1019 UINT i;
1020 HRESULT hres;
1022 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1023 lcid, rgDispId);
1025 for(i=0; i < cNames; i++)
1027 hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId + i);
1028 if(FAILED(hres))
1029 return hres;
1032 return S_OK;
1035 static HRESULT WINAPI scriptlet_Invoke(IDispatchEx *iface, DISPID dispIdMember,
1036 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1037 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1039 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1040 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1041 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1042 return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags,
1043 pDispParams, pVarResult, pExcepInfo, NULL);
1046 static HRESULT WINAPI scriptlet_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
1048 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1049 unsigned i;
1051 TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
1053 if (grfdex & ~(fdexNameCaseInsensitive|fdexNameCaseSensitive))
1054 FIXME("Unsupported grfdex %x\n", grfdex);
1056 for (i = 0; i < This->member_cnt; i++)
1058 if (grfdex & fdexNameCaseInsensitive)
1060 if (wcsicmp(This->members[i].name, bstrName)) continue;
1062 else if (wcscmp(This->members[i].name, bstrName)) continue;
1063 *pid = i + 1;
1064 return S_OK;
1067 WARN("Unknown property %s\n", debugstr_w(bstrName));
1068 return DISP_E_UNKNOWNNAME;
1071 static HRESULT WINAPI scriptlet_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *pdp,
1072 VARIANT *res, EXCEPINFO *pei, IServiceProvider *caller)
1074 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1075 struct object_member *member;
1077 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, pdp, res, pei, caller);
1079 if (id < 1 || id > This->member_cnt)
1081 WARN("Unknown id %xu\n", id);
1082 return DISP_E_MEMBERNOTFOUND;
1084 member = &This->members[id - 1];
1086 switch (member->type)
1088 case MEMBER_METHOD:
1089 if ((flags & ~DISPATCH_PROPERTYGET) != DISPATCH_METHOD)
1091 FIXME("unsupported method flags %x\n", flags);
1092 return DISP_E_MEMBERNOTFOUND;
1094 return IDispatchEx_InvokeEx(member->u.method.host->script_dispatch, member->u.method.id, lcid,
1095 DISPATCH_METHOD, pdp, res, pei, caller);
1096 case MEMBER_PROPERTY:
1097 if (flags & DISPATCH_PROPERTYGET)
1099 if (!member->u.property.get.host)
1101 FIXME("No %s getter\n", debugstr_w(member->name));
1102 return DISP_E_MEMBERNOTFOUND;
1104 return IDispatchEx_InvokeEx(member->u.property.get.host->script_dispatch, member->u.property.get.id, lcid,
1105 DISPATCH_METHOD, pdp, res, pei, caller);
1107 if (flags & DISPATCH_PROPERTYPUT)
1109 DISPPARAMS dp;
1111 if (!member->u.property.put.host)
1113 FIXME("No %s setter\n", debugstr_w(member->name));
1114 return DISP_E_MEMBERNOTFOUND;
1116 if (pdp->cNamedArgs != 1 || pdp->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)
1118 FIXME("no propput argument\n");
1119 return E_FAIL;
1121 dp = *pdp;
1122 dp.cNamedArgs = 0;
1123 return IDispatchEx_InvokeEx(member->u.property.put.host->script_dispatch, member->u.property.put.id, lcid,
1124 DISPATCH_METHOD, &dp, res, pei, caller);
1127 FIXME("unsupported flags %x\n", flags);
1130 return DISP_E_MEMBERNOTFOUND;
1133 static HRESULT WINAPI scriptlet_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
1135 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1136 FIXME("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
1137 return E_NOTIMPL;
1140 static HRESULT WINAPI scriptlet_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
1142 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1143 FIXME("(%p)->(%x)\n", This, id);
1144 return E_NOTIMPL;
1147 static HRESULT WINAPI scriptlet_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
1149 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1150 FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex);
1151 return E_NOTIMPL;
1154 static HRESULT WINAPI scriptlet_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
1156 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1157 FIXME("(%p)->(%x %p)\n", This, id, pbstrName);
1158 return E_NOTIMPL;
1161 static HRESULT WINAPI scriptlet_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
1163 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1164 FIXME("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
1165 return E_NOTIMPL;
1168 static HRESULT WINAPI scriptlet_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
1170 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1171 FIXME("(%p)->(%p)\n", This, ppunk);
1172 return E_NOTIMPL;
1175 static IDispatchExVtbl DispatchExVtbl = {
1176 scriptlet_QueryInterface,
1177 scriptlet_AddRef,
1178 scriptlet_Release,
1179 scriptlet_GetTypeInfoCount,
1180 scriptlet_GetTypeInfo,
1181 scriptlet_GetIDsOfNames,
1182 scriptlet_Invoke,
1183 scriptlet_GetDispID,
1184 scriptlet_InvokeEx,
1185 scriptlet_DeleteMemberByName,
1186 scriptlet_DeleteMemberByDispID,
1187 scriptlet_GetMemberProperties,
1188 scriptlet_GetMemberName,
1189 scriptlet_GetNextDispID,
1190 scriptlet_GetNameSpaceParent
1193 static HRESULT create_scriptlet_instance(struct scriptlet_factory *factory, IDispatchEx **disp)
1195 struct script_host *factory_host, *host;
1196 struct scriptlet_instance *obj;
1197 IDispatch *script_dispatch;
1198 HRESULT hres;
1200 if (!(obj = heap_alloc_zero(sizeof(*obj)))) return E_OUTOFMEMORY;
1202 obj->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
1203 obj->ref = 1;
1204 list_init(&obj->hosts);
1206 if (!(obj->global = heap_alloc(sizeof(*obj->global))))
1208 IDispatchEx_Release(&obj->IDispatchEx_iface);
1209 return E_OUTOFMEMORY;
1211 obj->global->IDispatchEx_iface.lpVtbl = &global_vtbl;
1212 obj->global->ref = 1;
1214 LIST_FOR_EACH_ENTRY(factory_host, &factory->hosts, struct script_host, entry)
1216 hres = create_script_host(factory_host->language, factory_host->active_script, &obj->hosts, &host);
1217 if (FAILED(hres)) break;
1218 host->object = obj;
1220 hres = IActiveScript_AddNamedItem(host->active_script, L"scriptlet",
1221 SCRIPTITEM_ISVISIBLE | SCRIPTITEM_GLOBALMEMBERS);
1222 if (FAILED(hres)) break;
1224 hres = IActiveScript_AddNamedItem(host->active_script, L"globals", SCRIPTITEM_ISVISIBLE);
1225 if (FAILED(hres)) break;
1227 hres = IActiveScript_GetScriptDispatch(host->active_script, NULL, &script_dispatch);
1228 if (FAILED(hres)) return hres;
1230 hres = IDispatch_QueryInterface(script_dispatch, &IID_IDispatchEx, (void**)&host->script_dispatch);
1231 IDispatch_Release(script_dispatch);
1232 if (FAILED(hres))
1234 FIXME("IDispatchEx not supported by script engine\n");
1235 return hres;
1239 if (SUCCEEDED(hres)) hres = parse_scripts(factory, &obj->hosts, TRUE);
1240 if (SUCCEEDED(hres)) hres = lookup_object_properties(obj, factory);
1241 if (FAILED(hres))
1243 IDispatchEx_Release(&obj->IDispatchEx_iface);
1244 return hres;
1247 *disp = &obj->IDispatchEx_iface;
1248 return S_OK;
1251 static const char *debugstr_xml_name(struct scriptlet_factory *factory)
1253 const WCHAR *str;
1254 UINT len;
1255 HRESULT hres;
1256 hres = IXmlReader_GetLocalName(factory->xml_reader, &str, &len);
1257 if (FAILED(hres)) return "#err";
1258 return debugstr_wn(str, len);
1261 static HRESULT next_xml_node(struct scriptlet_factory *factory, XmlNodeType *node_type)
1263 HRESULT hres;
1264 for (;;)
1266 hres = IXmlReader_Read(factory->xml_reader, node_type);
1267 if (FAILED(hres)) break;
1268 if (*node_type == XmlNodeType_Whitespace) continue;
1269 if (*node_type == XmlNodeType_ProcessingInstruction)
1271 FIXME("Ignoring processing instruction\n");
1272 continue;
1274 break;
1276 return hres;
1279 static BOOL is_xml_name(struct scriptlet_factory *factory, const WCHAR *name)
1281 const WCHAR *qname;
1282 UINT len;
1283 HRESULT hres;
1284 hres = IXmlReader_GetQualifiedName(factory->xml_reader, &qname, &len);
1285 return hres == S_OK && len == wcslen(name) && !memcmp(qname, name, len * sizeof(WCHAR));
1288 static HRESULT expect_end_element(struct scriptlet_factory *factory)
1290 XmlNodeType node_type;
1291 HRESULT hres;
1292 hres = next_xml_node(factory, &node_type);
1293 if (hres != S_OK || node_type != XmlNodeType_EndElement)
1295 FIXME("Unexpected node %u %s\n", node_type, debugstr_xml_name(factory));
1296 return E_FAIL;
1298 return S_OK;
1301 static HRESULT expect_no_attributes(struct scriptlet_factory *factory)
1303 UINT count;
1304 HRESULT hres;
1305 hres = IXmlReader_GetAttributeCount(factory->xml_reader, &count);
1306 if (FAILED(hres)) return hres;
1307 if (!count) return S_OK;
1308 FIXME("Unexpected attributes\n");
1309 return E_FAIL;
1312 static BOOL is_case_xml_name(struct scriptlet_factory *factory, const WCHAR *name)
1314 const WCHAR *qname;
1315 UINT len;
1316 HRESULT hres;
1317 hres = IXmlReader_GetQualifiedName(factory->xml_reader, &qname, &len);
1318 return hres == S_OK && len == wcslen(name) && !memicmp(qname, name, len * sizeof(WCHAR));
1321 static HRESULT read_xml_value(struct scriptlet_factory *factory, WCHAR **ret)
1323 const WCHAR *str;
1324 UINT len;
1325 HRESULT hres;
1326 hres = IXmlReader_GetValue(factory->xml_reader, &str, &len);
1327 if (FAILED(hres)) return hres;
1328 if (!(*ret = heap_alloc((len + 1) * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1329 memcpy(*ret, str, len * sizeof(WCHAR));
1330 (*ret)[len] = 0;
1331 return S_OK;
1334 static HRESULT parse_scriptlet_registration(struct scriptlet_factory *factory)
1336 HRESULT hres;
1338 TRACE("\n");
1340 if (factory->have_registration)
1342 FIXME("duplicated registration element\n");
1343 return E_FAIL;
1345 factory->have_registration = TRUE;
1347 for (;;)
1349 hres = IXmlReader_MoveToNextAttribute(factory->xml_reader);
1350 if (hres != S_OK) break;
1352 if (is_xml_name(factory, L"description"))
1354 if (factory->description)
1356 FIXME("Duplicated description\n");
1357 return E_FAIL;
1359 hres = read_xml_value(factory, &factory->description);
1360 if (FAILED(hres)) return hres;
1362 else if (is_case_xml_name(factory, L"progid"))
1364 if (factory->progid)
1366 FIXME("Duplicated progid\n");
1367 return E_FAIL;
1369 hres = read_xml_value(factory, &factory->progid);
1370 if (FAILED(hres)) return hres;
1372 else if (is_xml_name(factory, L"version"))
1374 if (factory->version)
1376 FIXME("Duplicated version\n");
1377 return E_FAIL;
1379 hres = read_xml_value(factory, &factory->version);
1380 if (FAILED(hres)) return hres;
1382 else if (is_xml_name(factory, L"classid"))
1384 if (factory->classid_str)
1386 FIXME("Duplicated classid attribute\n");
1387 return E_FAIL;
1389 hres = read_xml_value(factory, &factory->classid_str);
1390 if (FAILED(hres)) return hres;
1391 hres = IIDFromString(factory->classid_str, &factory->classid);
1392 if (FAILED(hres))
1394 FIXME("Invalid classid %s\n", debugstr_w(factory->classid_str));
1396 return E_FAIL;
1399 else
1401 FIXME("Unexpected attribute\n");
1402 return E_NOTIMPL;
1406 if (!factory->progid && !factory->classid_str)
1408 FIXME("Incomplet registration element\n");
1409 return E_FAIL;
1412 if (factory->progid)
1414 size_t progid_len = wcslen(factory->progid);
1415 size_t version_len = wcslen(factory->version);
1417 if (!(factory->versioned_progid = heap_alloc((progid_len + version_len + 2) * sizeof(WCHAR))))
1418 return E_OUTOFMEMORY;
1420 memcpy(factory->versioned_progid, factory->progid, (progid_len + 1) * sizeof(WCHAR));
1421 if (version_len)
1423 factory->versioned_progid[progid_len++] = '.';
1424 wcscpy(factory->versioned_progid + progid_len, factory->version);
1426 else factory->versioned_progid[progid_len] = 0;
1429 return expect_end_element(factory);
1432 static HRESULT parse_scriptlet_public(struct scriptlet_factory *factory)
1434 struct scriptlet_member *member, *member_iter;
1435 enum member_type member_type;
1436 XmlNodeType node_type;
1437 BOOL empty;
1438 HRESULT hres;
1440 TRACE("\n");
1442 if (factory->have_public)
1444 FIXME("duplicated public element\n");
1445 return E_FAIL;
1447 factory->have_public = TRUE;
1449 for (;;)
1451 hres = next_xml_node(factory, &node_type);
1452 if (FAILED(hres)) return hres;
1453 if (node_type == XmlNodeType_EndElement) break;
1454 if (node_type != XmlNodeType_Element)
1456 FIXME("Unexpected node type %u\n", node_type);
1457 return E_FAIL;
1460 if (is_xml_name(factory, L"method"))
1461 member_type = MEMBER_METHOD;
1462 else if (is_xml_name(factory, L"property"))
1463 member_type = MEMBER_PROPERTY;
1464 else
1466 FIXME("Unexpected element %s\n", debugstr_xml_name(factory));
1467 return E_NOTIMPL;
1470 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1472 hres = IXmlReader_MoveToAttributeByName(factory->xml_reader, L"name", NULL);
1473 if (hres != S_OK)
1475 FIXME("Missing method name\n");
1476 return E_FAIL;
1479 if (!(member = heap_alloc(sizeof(*member)))) return E_OUTOFMEMORY;
1480 member->type = member_type;
1482 hres = read_xml_value(factory, &member->name);
1483 if (FAILED(hres))
1485 heap_free(member);
1486 return hres;
1489 LIST_FOR_EACH_ENTRY(member_iter, &factory->members, struct scriptlet_member, entry)
1491 if (!wcsicmp(member_iter->name, member->name))
1493 FIXME("Duplicated member %s\n", debugstr_w(member->name));
1494 heap_free(member);
1495 return E_FAIL;
1498 list_add_tail(&factory->members, &member->entry);
1500 switch (member_type)
1502 case MEMBER_METHOD:
1503 list_init(&member->u.parameters);
1505 if (empty) break;
1506 for (;;)
1508 struct method_parameter *parameter;
1510 hres = next_xml_node(factory, &node_type);
1511 if (FAILED(hres)) return hres;
1512 if (node_type == XmlNodeType_EndElement) break;
1513 if (node_type != XmlNodeType_Element)
1515 FIXME("Unexpected node type %u\n", node_type);
1516 return E_FAIL;
1518 if (!is_case_xml_name(factory, L"parameter"))
1520 FIXME("Unexpected method element\n");
1521 return E_FAIL;
1524 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1526 hres = IXmlReader_MoveToAttributeByName(factory->xml_reader, L"name", NULL);
1527 if (hres != S_OK)
1529 FIXME("Missing parameter name\n");
1530 return E_FAIL;
1533 if (!(parameter = heap_alloc_zero(sizeof(*parameter)))) return E_OUTOFMEMORY;
1534 list_add_tail(&member->u.parameters, &parameter->entry);
1536 hres = read_xml_value(factory, &parameter->name);
1537 if (FAILED(hres)) return hres;
1538 if (!empty && FAILED(hres = expect_end_element(factory))) return hres;
1540 break;
1542 case MEMBER_PROPERTY:
1543 member->u.flags = 0;
1545 if (empty) break;
1546 for (;;)
1548 hres = next_xml_node(factory, &node_type);
1549 if (FAILED(hres)) return hres;
1550 if (node_type == XmlNodeType_EndElement) break;
1551 if (node_type != XmlNodeType_Element)
1553 FIXME("Unexpected node type %u\n", node_type);
1554 return E_FAIL;
1556 if (is_case_xml_name(factory, L"get"))
1558 if (member->u.flags & PROP_GETTER)
1560 FIXME("Duplicated getter\n");
1561 return E_FAIL;
1563 member->u.flags |= PROP_GETTER;
1565 else if (is_case_xml_name(factory, L"put"))
1567 if (member->u.flags & PROP_SETTER)
1569 FIXME("Duplicated setter\n");
1570 return E_FAIL;
1572 member->u.flags |= PROP_SETTER;
1574 else
1576 FIXME("Unexpected property element %s\n", debugstr_xml_name(factory));
1577 return E_FAIL;
1580 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1581 if (!empty && FAILED(hres = expect_end_element(factory))) return hres;
1583 if (!member->u.flags)
1585 FIXME("No getter or setter\n");
1586 return E_NOTIMPL;
1588 break;
1590 if (FAILED(hres)) return hres;
1593 return S_OK;
1596 static HRESULT parse_scriptlet_script(struct scriptlet_factory *factory, struct scriptlet_script *script)
1598 XmlNodeType node_type;
1599 size_t buf_size, size;
1600 WCHAR *new_body;
1601 DWORD read;
1602 HRESULT hres;
1604 TRACE("\n");
1606 for (;;)
1608 hres = IXmlReader_MoveToNextAttribute(factory->xml_reader);
1609 if (hres != S_OK) break;
1611 if (is_xml_name(factory, L"language"))
1613 if (script->language)
1615 FIXME("Duplicated language\n");
1616 return E_FAIL;
1618 hres = read_xml_value(factory, &script->language);
1619 if (FAILED(hres)) return hres;
1621 else
1623 FIXME("Unexpected attribute\n");
1624 return E_NOTIMPL;
1628 if (!script->language)
1630 FIXME("Language not specified\n");
1631 return E_FAIL;
1634 if (FAILED(hres = next_xml_node(factory, &node_type))) return hres;
1636 if (node_type != XmlNodeType_Text && node_type != XmlNodeType_CDATA)
1638 FIXME("Unexpected node type %u\n", node_type);
1639 return E_FAIL;
1642 if (!(script->body = heap_alloc((buf_size = 1024) * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1643 size = 0;
1645 for (;;)
1647 read = 0;
1648 hres = IXmlReader_ReadValueChunk(factory->xml_reader, script->body + size, buf_size - size - 1, &read);
1649 if (FAILED(hres)) return hres;
1650 size += read;
1651 if (hres == S_FALSE) break;
1652 if (size + 1 == buf_size)
1654 if (!(new_body = heap_realloc(script->body, (buf_size *= 2) * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1655 script->body = new_body;
1658 script->body[size++] = 0;
1659 if (size != buf_size) script->body = heap_realloc(script->body, size * sizeof(WCHAR));
1661 TRACE("body %s\n", debugstr_w(script->body));
1662 return expect_end_element(factory);
1665 static HRESULT parse_scriptlet_file(struct scriptlet_factory *factory, const WCHAR *url)
1667 XmlNodeType node_type;
1668 IBindCtx *bind_ctx;
1669 IStream *stream;
1670 HRESULT hres;
1672 hres = CreateURLMoniker(NULL, url, &factory->moniker);
1673 if (FAILED(hres))
1675 WARN("CreateURLMoniker failed: %08x\n", hres);
1676 return hres;
1679 hres = CreateBindCtx(0, &bind_ctx);
1680 if(FAILED(hres))
1681 return hres;
1683 hres = IMoniker_BindToStorage(factory->moniker, bind_ctx, NULL, &IID_IStream, (void**)&stream);
1684 IBindCtx_Release(bind_ctx);
1685 if (FAILED(hres))
1686 return hres;
1688 hres = CreateXmlReader(&IID_IXmlReader, (void**)&factory->xml_reader, NULL);
1689 if(SUCCEEDED(hres))
1690 hres = IXmlReader_SetInput(factory->xml_reader, (IUnknown*)stream);
1691 IStream_Release(stream);
1692 if (FAILED(hres))
1693 return hres;
1695 hres = next_xml_node(factory, &node_type);
1696 if (hres == S_OK && node_type == XmlNodeType_XmlDeclaration)
1697 hres = next_xml_node(factory, &node_type);
1698 if (FAILED(hres))
1699 return hres;
1701 if (node_type != XmlNodeType_Element || !is_xml_name(factory, L"component"))
1703 FIXME("Unexpected %s element\n", debugstr_xml_name(factory));
1704 return E_FAIL;
1707 hres = expect_no_attributes(factory);
1708 if (FAILED(hres)) return hres;
1710 for (;;)
1712 hres = next_xml_node(factory, &node_type);
1713 if (FAILED(hres)) return hres;
1714 if (node_type == XmlNodeType_EndElement) break;
1715 if (node_type != XmlNodeType_Element)
1717 FIXME("Unexpected node type %u\n", node_type);
1718 return E_FAIL;
1721 if (is_xml_name(factory, L"registration"))
1722 hres = parse_scriptlet_registration(factory);
1723 else if (is_xml_name(factory, L"public"))
1724 hres = parse_scriptlet_public(factory);
1725 else if (is_xml_name(factory, L"script"))
1727 struct scriptlet_script *script;
1728 if (!(script = heap_alloc_zero(sizeof(*script)))) return E_OUTOFMEMORY;
1729 list_add_tail(&factory->scripts, &script->entry);
1730 hres = parse_scriptlet_script(factory, script);
1731 if (FAILED(hres)) return hres;
1733 else
1735 FIXME("Unexpected element %s\n", debugstr_xml_name(factory));
1736 return E_NOTIMPL;
1738 if (FAILED(hres)) return hres;
1741 hres = next_xml_node(factory, &node_type);
1742 if (hres != S_FALSE)
1744 FIXME("Unexpected node type %u\n", node_type);
1745 return E_FAIL;
1747 return S_OK;
1750 static inline struct scriptlet_factory *impl_from_IClassFactory(IClassFactory *iface)
1752 return CONTAINING_RECORD(iface, struct scriptlet_factory, IClassFactory_iface);
1755 static HRESULT WINAPI scriptlet_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
1757 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1759 if (IsEqualGUID(&IID_IUnknown, riid))
1761 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
1762 *ppv = &This->IClassFactory_iface;
1764 else if (IsEqualGUID(&IID_IClassFactory, riid))
1766 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
1767 *ppv = &This->IClassFactory_iface;
1769 else
1771 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
1772 *ppv = NULL;
1773 return E_NOINTERFACE;
1776 IUnknown_AddRef((IUnknown *)*ppv);
1777 return S_OK;
1780 static ULONG WINAPI scriptlet_factory_AddRef(IClassFactory *iface)
1782 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1783 ULONG ref = InterlockedIncrement(&This->ref);
1785 TRACE("(%p) ref=%d\n", This, ref);
1787 return ref;
1790 static ULONG WINAPI scriptlet_factory_Release(IClassFactory *iface)
1792 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1793 ULONG ref = InterlockedDecrement(&This->ref);
1795 TRACE("(%p) ref=%d\n", This, ref);
1797 if (!ref)
1799 if (This->moniker) IMoniker_Release(This->moniker);
1800 if (This->xml_reader) IXmlReader_Release(This->xml_reader);
1801 detach_script_hosts(&This->hosts);
1802 while (!list_empty(&This->members))
1804 struct scriptlet_member *member = LIST_ENTRY(list_head(&This->members), struct scriptlet_member, entry);
1805 list_remove(&member->entry);
1806 heap_free(member->name);
1807 if (member->type == MEMBER_METHOD)
1809 while (!list_empty(&member->u.parameters))
1811 struct method_parameter *parameter = LIST_ENTRY(list_head(&member->u.parameters), struct method_parameter, entry);
1812 list_remove(&parameter->entry);
1813 heap_free(parameter->name);
1814 heap_free(parameter);
1817 heap_free(member);
1819 while (!list_empty(&This->scripts))
1821 struct scriptlet_script *script = LIST_ENTRY(list_head(&This->scripts), struct scriptlet_script, entry);
1822 list_remove(&script->entry);
1823 heap_free(script->language);
1824 heap_free(script->body);
1825 heap_free(script);
1827 heap_free(This->classid_str);
1828 heap_free(This->description);
1829 heap_free(This->versioned_progid);
1830 heap_free(This->progid);
1831 heap_free(This->version);
1832 heap_free(This);
1834 return ref;
1837 static HRESULT WINAPI scriptlet_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1839 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1840 IDispatchEx *disp;
1841 HRESULT hres;
1843 TRACE("(%p)->(%p %s %p)\n", This, outer, debugstr_guid(riid), ppv);
1845 if (outer) FIXME("outer not supported\n");
1847 if (list_empty(&This->hosts))
1849 hres = create_scriptlet_hosts(This, &This->hosts);
1850 if (FAILED(hres)) return hres;
1852 hres = parse_scripts(This, &This->hosts, FALSE);
1853 if (FAILED(hres))
1855 detach_script_hosts(&This->hosts);
1856 return hres;
1860 hres = create_scriptlet_instance(This, &disp);
1861 if (FAILED(hres)) return hres;
1863 hres = IDispatchEx_QueryInterface(disp, riid, ppv);
1864 IDispatchEx_Release(disp);
1865 return hres;
1868 static HRESULT WINAPI scriptlet_factory_LockServer(IClassFactory *iface, BOOL fLock)
1870 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1871 TRACE("(%p)->(%x)\n", This, fLock);
1872 return S_OK;
1875 static const struct IClassFactoryVtbl scriptlet_factory_vtbl =
1877 scriptlet_factory_QueryInterface,
1878 scriptlet_factory_AddRef,
1879 scriptlet_factory_Release,
1880 scriptlet_factory_CreateInstance,
1881 scriptlet_factory_LockServer
1884 static HRESULT create_scriptlet_factory(const WCHAR *url, struct scriptlet_factory **ret)
1886 struct scriptlet_factory *factory;
1887 HRESULT hres;
1889 TRACE("%s\n", debugstr_w(url));
1891 if (!(factory = heap_alloc_zero(sizeof(*factory))))
1893 IClassFactory_Release(&factory->IClassFactory_iface);
1894 return E_OUTOFMEMORY;
1897 factory->IClassFactory_iface.lpVtbl = &scriptlet_factory_vtbl;
1898 factory->ref = 1;
1899 list_init(&factory->hosts);
1900 list_init(&factory->members);
1901 list_init(&factory->scripts);
1903 hres = parse_scriptlet_file(factory, url);
1904 if (FAILED(hres))
1906 IClassFactory_Release(&factory->IClassFactory_iface);
1907 return hres;
1910 *ret = factory;
1911 return S_OK;
1914 static HRESULT register_scriptlet(struct scriptlet_factory *factory)
1916 HKEY key, clsid_key, obj_key;
1917 LSTATUS status;
1918 HRESULT hres;
1920 if (factory->classid_str)
1922 WCHAR *url;
1924 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"CLSID", &clsid_key);
1925 if (status) return E_ACCESSDENIED;
1927 status = RegCreateKeyW(clsid_key, factory->classid_str, &obj_key);
1928 RegCloseKey(clsid_key);
1929 if (status) return E_ACCESSDENIED;
1931 hres = IMoniker_GetDisplayName(factory->moniker, NULL, NULL, &url);
1932 if (FAILED(hres))
1934 RegCloseKey(obj_key);
1935 return hres;
1937 status = RegCreateKeyW(obj_key, L"ScriptletURL", &key);
1938 if (!status)
1940 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)url,
1941 (wcslen(url) + 1) * sizeof(WCHAR));
1942 RegCloseKey(key);
1944 CoTaskMemFree(url);
1946 if (factory->description)
1947 status = RegSetValueExW(obj_key, NULL, 0, REG_SZ, (BYTE*)factory->description,
1948 (wcslen(factory->description) + 1) * sizeof(WCHAR));
1950 if (!status)
1952 status = RegCreateKeyW(obj_key, L"InprocServer32", &key);
1953 if (!status)
1955 WCHAR str[MAX_PATH];
1956 GetModuleFileNameW(scrobj_instance, str, MAX_PATH);
1957 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)str, (wcslen(str) + 1) * sizeof(WCHAR));
1958 RegCloseKey(key);
1962 if (!status && factory->versioned_progid)
1964 status = RegCreateKeyW(obj_key, L"ProgID", &key);
1965 if (!status)
1967 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->versioned_progid,
1968 (wcslen(factory->versioned_progid) + 1) * sizeof(WCHAR));
1969 RegCloseKey(key);
1973 if (!status && factory->progid)
1975 status = RegCreateKeyW(obj_key, L"VersionIndependentProgID", &key);
1976 if (!status)
1978 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->progid,
1979 (wcslen(factory->progid) + 1) * sizeof(WCHAR));
1980 RegCloseKey(key);
1984 RegCloseKey(obj_key);
1985 if (status) return E_ACCESSDENIED;
1988 if (factory->progid)
1990 status = RegCreateKeyW(HKEY_CLASSES_ROOT, factory->progid, &key);
1991 if (status) return E_ACCESSDENIED;
1993 if (factory->description)
1994 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->description,
1995 (wcslen(factory->description) + 1) * sizeof(WCHAR));
1997 if (!status && factory->classid_str)
1999 status = RegCreateKeyW(key, L"CLSID", &clsid_key);
2000 if (!status)
2002 status = RegSetValueExW(clsid_key, NULL, 0, REG_SZ, (BYTE*)factory->classid_str,
2003 (wcslen(factory->classid_str) + 1) * sizeof(WCHAR));
2004 RegCloseKey(clsid_key);
2008 RegCloseKey(key);
2009 if (status) return E_ACCESSDENIED;
2012 if (factory->versioned_progid)
2014 status = RegCreateKeyW(HKEY_CLASSES_ROOT, factory->versioned_progid, &key);
2015 if (status) return E_ACCESSDENIED;
2017 if (factory->description)
2018 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->description,
2019 (wcslen(factory->description) + 1) * sizeof(WCHAR));
2021 if (!status && factory->classid_str)
2023 status = RegCreateKeyW(key, L"CLSID", &clsid_key);
2024 if (!status)
2026 status = RegSetValueExW(clsid_key, NULL, 0, REG_SZ, (BYTE*)factory->classid_str,
2027 (wcslen(factory->classid_str) + 1) * sizeof(WCHAR));
2028 RegCloseKey(clsid_key);
2032 RegCloseKey(key);
2033 if (status) return E_ACCESSDENIED;
2036 return S_OK;
2039 static HRESULT unregister_scriptlet(struct scriptlet_factory *factory)
2041 LSTATUS status;
2043 if (factory->classid_str)
2045 HKEY clsid_key;
2046 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"CLSID", &clsid_key);
2047 if (!status)
2049 RegDeleteTreeW(clsid_key, factory->classid_str);
2050 RegCloseKey(clsid_key);
2054 if (factory->progid) RegDeleteTreeW(HKEY_CLASSES_ROOT, factory->progid);
2055 if (factory->versioned_progid) RegDeleteTreeW(HKEY_CLASSES_ROOT, factory->versioned_progid);
2056 return S_OK;
2059 struct scriptlet_typelib
2061 IGenScriptletTLib IGenScriptletTLib_iface;
2062 LONG ref;
2064 BSTR guid;
2067 static inline struct scriptlet_typelib *impl_from_IGenScriptletTLib(IGenScriptletTLib *iface)
2069 return CONTAINING_RECORD(iface, struct scriptlet_typelib, IGenScriptletTLib_iface);
2072 static HRESULT WINAPI scriptlet_typelib_QueryInterface(IGenScriptletTLib *iface, REFIID riid, void **obj)
2074 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2076 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), obj);
2078 if (IsEqualIID(riid, &IID_IGenScriptletTLib) ||
2079 IsEqualIID(riid, &IID_IDispatch) ||
2080 IsEqualIID(riid, &IID_IUnknown))
2082 *obj = iface;
2083 IGenScriptletTLib_AddRef(iface);
2084 return S_OK;
2087 *obj = NULL;
2088 return E_NOINTERFACE;
2091 static ULONG WINAPI scriptlet_typelib_AddRef(IGenScriptletTLib *iface)
2093 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2094 ULONG ref = InterlockedIncrement(&This->ref);
2095 TRACE("(%p)->(%u)\n", This, ref);
2096 return ref;
2099 static ULONG WINAPI scriptlet_typelib_Release(IGenScriptletTLib *iface)
2101 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2102 LONG ref = InterlockedDecrement(&This->ref);
2104 TRACE("(%p)->(%u)\n", This, ref);
2106 if (!ref)
2108 SysFreeString(This->guid);
2109 HeapFree(GetProcessHeap(), 0, This);
2112 return ref;
2115 static HRESULT WINAPI scriptlet_typelib_GetTypeInfoCount(IGenScriptletTLib *iface, UINT *count)
2117 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2119 TRACE("(%p, %p)\n", This, count);
2121 *count = 1;
2122 return S_OK;
2125 static HRESULT WINAPI scriptlet_typelib_GetTypeInfo(IGenScriptletTLib *iface, UINT index, LCID lcid,
2126 ITypeInfo **tinfo)
2128 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2130 TRACE("(%p, %u, %x, %p)\n", This, index, lcid, tinfo);
2132 return get_typeinfo(IGenScriptletTLib_tid, tinfo);
2135 static HRESULT WINAPI scriptlet_typelib_GetIDsOfNames(IGenScriptletTLib *iface, REFIID riid, LPOLESTR *names,
2136 UINT cNames, LCID lcid, DISPID *dispid)
2138 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2139 ITypeInfo *typeinfo;
2140 HRESULT hr;
2142 TRACE("(%p, %s, %p, %u, %x, %p)\n", This, debugstr_guid(riid), names, cNames, lcid, dispid);
2144 hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo);
2145 if (SUCCEEDED(hr))
2147 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, cNames, dispid);
2148 ITypeInfo_Release(typeinfo);
2151 return hr;
2154 static HRESULT WINAPI scriptlet_typelib_Invoke(IGenScriptletTLib *iface, DISPID dispid, REFIID riid,
2155 LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *ei, UINT *argerr)
2157 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2158 ITypeInfo *typeinfo;
2159 HRESULT hr;
2161 TRACE("(%p, %d, %s, %x, %x, %p, %p, %p, %p)\n", This, dispid, debugstr_guid(riid), lcid, flags,
2162 params, result, ei, argerr);
2164 hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo);
2165 if (SUCCEEDED(hr))
2167 hr = ITypeInfo_Invoke(typeinfo, &This->IGenScriptletTLib_iface, dispid, flags,
2168 params, result, ei, argerr);
2169 ITypeInfo_Release(typeinfo);
2172 return hr;
2175 static HRESULT WINAPI scriptlet_typelib_AddURL(IGenScriptletTLib *iface, BSTR url)
2177 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2179 FIXME("(%p, %s): stub\n", This, debugstr_w(url));
2181 return E_NOTIMPL;
2184 static HRESULT WINAPI scriptlet_typelib_put_Path(IGenScriptletTLib *iface, BSTR path)
2186 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2188 FIXME("(%p, %s): stub\n", This, debugstr_w(path));
2190 return E_NOTIMPL;
2193 static HRESULT WINAPI scriptlet_typelib_get_Path(IGenScriptletTLib *iface, BSTR *path)
2195 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2197 FIXME("(%p, %p): stub\n", This, path);
2199 return E_NOTIMPL;
2202 static HRESULT WINAPI scriptlet_typelib_put_Doc(IGenScriptletTLib *iface, BSTR doc)
2204 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2206 FIXME("(%p, %s): stub\n", This, debugstr_w(doc));
2208 return E_NOTIMPL;
2211 static HRESULT WINAPI scriptlet_typelib_get_Doc(IGenScriptletTLib *iface, BSTR *doc)
2213 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2215 FIXME("(%p, %p): stub\n", This, doc);
2217 return E_NOTIMPL;
2220 static HRESULT WINAPI scriptlet_typelib_put_Name(IGenScriptletTLib *iface, BSTR name)
2222 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2224 FIXME("(%p, %s): stub\n", This, debugstr_w(name));
2226 return E_NOTIMPL;
2229 static HRESULT WINAPI scriptlet_typelib_get_Name(IGenScriptletTLib *iface, BSTR *name)
2231 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2233 FIXME("(%p, %p): stub\n", This, name);
2235 return E_NOTIMPL;
2238 static HRESULT WINAPI scriptlet_typelib_put_MajorVersion(IGenScriptletTLib *iface, WORD version)
2240 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2242 FIXME("(%p, %x): stub\n", This, version);
2244 return E_NOTIMPL;
2247 static HRESULT WINAPI scriptlet_typelib_get_MajorVersion(IGenScriptletTLib *iface, WORD *version)
2249 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2251 FIXME("(%p, %p): stub\n", This, version);
2253 return E_NOTIMPL;
2256 static HRESULT WINAPI scriptlet_typelib_put_MinorVersion(IGenScriptletTLib *iface, WORD version)
2258 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2260 FIXME("(%p, %x): stub\n", This, version);
2262 return E_NOTIMPL;
2265 static HRESULT WINAPI scriptlet_typelib_get_MinorVersion(IGenScriptletTLib *iface, WORD *version)
2267 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2269 FIXME("(%p, %p): stub\n", This, version);
2271 return E_NOTIMPL;
2274 static HRESULT WINAPI scriptlet_typelib_Write(IGenScriptletTLib *iface)
2276 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2278 FIXME("(%p): stub\n", This);
2280 return E_NOTIMPL;
2283 static HRESULT WINAPI scriptlet_typelib_Reset(IGenScriptletTLib *iface)
2285 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2287 FIXME("(%p): stub\n", This);
2289 return E_NOTIMPL;
2292 static HRESULT WINAPI scriptlet_typelib_put_GUID(IGenScriptletTLib *iface, BSTR guid)
2294 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2296 FIXME("(%p, %s): stub\n", This, debugstr_w(guid));
2298 return E_NOTIMPL;
2301 static HRESULT WINAPI scriptlet_typelib_get_GUID(IGenScriptletTLib *iface, BSTR *ret)
2303 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2305 TRACE("(%p, %p)\n", This, ret);
2307 *ret = NULL;
2309 if (!This->guid)
2311 WCHAR guidW[39];
2312 GUID guid;
2313 HRESULT hr;
2315 hr = CoCreateGuid(&guid);
2316 if (FAILED(hr))
2317 return hr;
2319 hr = StringFromGUID2(&guid, guidW, ARRAY_SIZE(guidW));
2320 if (FAILED(hr))
2321 return hr;
2323 if (!(This->guid = SysAllocString(guidW)))
2324 return E_OUTOFMEMORY;
2327 *ret = SysAllocString(This->guid);
2328 return *ret ? S_OK : E_OUTOFMEMORY;
2331 static const IGenScriptletTLibVtbl scriptlet_typelib_vtbl =
2333 scriptlet_typelib_QueryInterface,
2334 scriptlet_typelib_AddRef,
2335 scriptlet_typelib_Release,
2336 scriptlet_typelib_GetTypeInfoCount,
2337 scriptlet_typelib_GetTypeInfo,
2338 scriptlet_typelib_GetIDsOfNames,
2339 scriptlet_typelib_Invoke,
2340 scriptlet_typelib_AddURL,
2341 scriptlet_typelib_put_Path,
2342 scriptlet_typelib_get_Path,
2343 scriptlet_typelib_put_Doc,
2344 scriptlet_typelib_get_Doc,
2345 scriptlet_typelib_put_Name,
2346 scriptlet_typelib_get_Name,
2347 scriptlet_typelib_put_MajorVersion,
2348 scriptlet_typelib_get_MajorVersion,
2349 scriptlet_typelib_put_MinorVersion,
2350 scriptlet_typelib_get_MinorVersion,
2351 scriptlet_typelib_Write,
2352 scriptlet_typelib_Reset,
2353 scriptlet_typelib_put_GUID,
2354 scriptlet_typelib_get_GUID
2357 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
2359 TRACE("%p, %u, %p\n", hinst, reason, reserved);
2361 switch (reason)
2363 case DLL_PROCESS_ATTACH:
2364 DisableThreadLibraryCalls(hinst);
2365 scrobj_instance = hinst;
2366 break;
2367 case DLL_PROCESS_DETACH:
2368 if (reserved) break;
2369 release_typelib();
2370 break;
2372 return TRUE;
2375 /***********************************************************************
2376 * DllRegisterServer (scrobj.@)
2378 HRESULT WINAPI DllRegisterServer(void)
2380 TRACE("()\n");
2381 return __wine_register_resources(scrobj_instance);
2384 /***********************************************************************
2385 * DllUnregisterServer (scrobj.@)
2387 HRESULT WINAPI DllUnregisterServer(void)
2389 TRACE("()\n");
2390 return __wine_unregister_resources(scrobj_instance);
2393 /***********************************************************************
2394 * DllInstall (scrobj.@)
2396 HRESULT WINAPI DllInstall(BOOL install, const WCHAR *arg)
2398 struct scriptlet_factory *factory;
2399 HRESULT hres;
2401 if (install)
2403 hres = DllRegisterServer();
2404 if (!arg || FAILED(hres)) return hres;
2406 else if (!arg)
2407 return DllUnregisterServer();
2409 hres = create_scriptlet_factory(arg, &factory);
2410 if (SUCCEEDED(hres))
2412 if (factory->have_registration)
2414 /* validate scripts */
2415 hres = create_scriptlet_hosts(factory, &factory->hosts);
2416 if (SUCCEEDED(hres)) hres = parse_scripts(factory, &factory->hosts, FALSE);
2418 else
2420 FIXME("No registration info\n");
2421 hres = E_FAIL;
2423 if (SUCCEEDED(hres))
2425 if (install)
2426 hres = register_scriptlet(factory);
2427 else
2428 hres = unregister_scriptlet(factory);
2430 IClassFactory_Release(&factory->IClassFactory_iface);
2433 return hres;
2436 static HRESULT WINAPI scriptlet_typelib_CreateInstance(IClassFactory *factory, IUnknown *outer, REFIID riid, void **obj)
2438 struct scriptlet_typelib *This;
2439 HRESULT hr;
2441 TRACE("(%p, %p, %s, %p)\n", factory, outer, debugstr_guid(riid), obj);
2443 *obj = NULL;
2445 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2446 if (!This)
2447 return E_OUTOFMEMORY;
2449 This->IGenScriptletTLib_iface.lpVtbl = &scriptlet_typelib_vtbl;
2450 This->ref = 1;
2451 This->guid = NULL;
2453 hr = IGenScriptletTLib_QueryInterface(&This->IGenScriptletTLib_iface, riid, obj);
2454 IGenScriptletTLib_Release(&This->IGenScriptletTLib_iface);
2455 return hr;
2458 static HRESULT WINAPI scrruncf_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2460 *ppv = NULL;
2462 if (IsEqualGUID(&IID_IUnknown, riid))
2464 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
2465 *ppv = iface;
2467 else if (IsEqualGUID(&IID_IClassFactory, riid))
2469 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
2470 *ppv = iface;
2473 if (*ppv)
2475 IUnknown_AddRef((IUnknown *)*ppv);
2476 return S_OK;
2479 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
2480 return E_NOINTERFACE;
2483 static ULONG WINAPI scrruncf_AddRef(IClassFactory *iface)
2485 TRACE("(%p)\n", iface);
2486 return 2;
2489 static ULONG WINAPI scrruncf_Release(IClassFactory *iface)
2491 TRACE("(%p)\n", iface);
2492 return 1;
2495 static HRESULT WINAPI scrruncf_LockServer(IClassFactory *iface, BOOL fLock)
2497 TRACE("(%p)->(%x)\n", iface, fLock);
2498 return S_OK;
2501 static const struct IClassFactoryVtbl scriptlet_typelib_factory_vtbl =
2503 scrruncf_QueryInterface,
2504 scrruncf_AddRef,
2505 scrruncf_Release,
2506 scriptlet_typelib_CreateInstance,
2507 scrruncf_LockServer
2510 static IClassFactory scriptlet_typelib_factory = { &scriptlet_typelib_factory_vtbl };
2512 /***********************************************************************
2513 * DllGetClassObject (scrobj.@)
2515 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
2517 WCHAR key_name[128], *p;
2518 LONG size = 0;
2519 LSTATUS status;
2521 if (IsEqualGUID(&CLSID_TypeLib, rclsid))
2523 TRACE("(Scriptlet.TypeLib %s %p)\n", debugstr_guid(riid), ppv);
2524 return IClassFactory_QueryInterface(&scriptlet_typelib_factory, riid, ppv);
2527 wcscpy(key_name, L"CLSID\\");
2528 p = key_name + wcslen(key_name);
2529 p += StringFromGUID2(rclsid, p, ARRAY_SIZE(key_name) - (p - key_name)) - 1;
2530 wcscpy(p, L"\\ScriptletURL");
2531 status = RegQueryValueW(HKEY_CLASSES_ROOT, key_name, NULL, &size);
2532 if (!status)
2534 struct scriptlet_factory *factory;
2535 WCHAR *url;
2536 HRESULT hres;
2538 if (!(url = heap_alloc(size * sizeof(WCHAR)))) return E_OUTOFMEMORY;
2539 status = RegQueryValueW(HKEY_CLASSES_ROOT, key_name, url, &size);
2541 hres = create_scriptlet_factory(url, &factory);
2542 heap_free(url);
2543 if (FAILED(hres)) return hres;
2545 hres = IClassFactory_QueryInterface(&factory->IClassFactory_iface, riid, ppv);
2546 IClassFactory_Release(&factory->IClassFactory_iface);
2547 return hres;
2550 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
2551 return CLASS_E_CLASSNOTAVAILABLE;
2554 /***********************************************************************
2555 * DllCanUnloadNow (scrobj.@)
2557 HRESULT WINAPI DllCanUnloadNow(void)
2559 return S_FALSE;