wined3d: Use return type to return result from read_dword.
[wine.git] / dlls / scrobj / scrobj.c
blob5056977624aeccb1c2db52aef6e896bfc7455d96
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/list.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(scrobj);
41 #ifdef _WIN64
43 #define IActiveScriptParse_Release IActiveScriptParse64_Release
44 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
45 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
47 #else
49 #define IActiveScriptParse_Release IActiveScriptParse32_Release
50 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
51 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
53 #endif
55 static HINSTANCE scrobj_instance;
57 enum member_type
59 MEMBER_METHOD,
60 MEMBER_PROPERTY
63 #define PROP_GETTER 0x01
64 #define PROP_SETTER 0x02
66 struct scriptlet_member
68 struct list entry;
69 enum member_type type;
70 WCHAR *name;
71 union
73 struct list parameters;
74 unsigned int flags;
75 } u;
78 struct method_parameter
80 struct list entry;
81 WCHAR *name;
84 struct scriptlet_script
86 struct list entry;
87 WCHAR *language;
88 WCHAR *body;
91 struct scriptlet_global
93 IDispatchEx IDispatchEx_iface;
94 LONG ref;
97 struct scriptlet_factory
99 IClassFactory IClassFactory_iface;
101 LONG ref;
103 IXmlReader *xml_reader;
104 IMoniker *moniker;
106 BOOL have_registration;
107 BOOL have_public;
108 WCHAR *description;
109 WCHAR *progid;
110 WCHAR *versioned_progid;
111 WCHAR *version;
112 WCHAR *classid_str;
113 CLSID classid;
115 struct list hosts;
116 struct list members;
117 struct list scripts;
120 struct script_reference
122 struct script_host *host;
123 DISPID id;
126 struct object_member
128 enum member_type type;
129 BSTR name;
130 union
132 struct script_reference method;
133 struct
135 struct script_reference get;
136 struct script_reference put;
137 } property;
138 } u;
141 struct scriptlet_instance
143 IDispatchEx IDispatchEx_iface;
144 LONG ref;
145 struct list hosts;
146 struct scriptlet_global *global;
147 unsigned member_cnt;
148 struct object_member *members;
151 struct script_host
153 IActiveScriptSite IActiveScriptSite_iface;
154 IActiveScriptSiteWindow IActiveScriptSiteWindow_iface;
155 IServiceProvider IServiceProvider_iface;
157 LONG ref;
158 struct list entry;
160 WCHAR *language;
162 IActiveScript *active_script;
163 IActiveScriptParse *parser;
164 IDispatchEx *script_dispatch;
165 struct scriptlet_instance *object;
166 SCRIPTSTATE state;
167 BOOL cloned;
170 typedef enum tid_t
172 NULL_tid,
173 IGenScriptletTLib_tid,
174 LAST_tid
175 } tid_t;
177 static ITypeLib *typelib;
178 static ITypeInfo *typeinfos[LAST_tid];
180 static REFIID tid_ids[] = {
181 &IID_NULL,
182 &IID_IGenScriptletTLib,
185 static HRESULT load_typelib(void)
187 HRESULT hres;
188 ITypeLib *tl;
190 if (typelib)
191 return S_OK;
193 hres = LoadRegTypeLib(&LIBID_Scriptlet, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
194 if (FAILED(hres))
196 ERR("LoadRegTypeLib failed: %08lx\n", hres);
197 return hres;
200 if (InterlockedCompareExchangePointer((void **)&typelib, tl, NULL))
201 ITypeLib_Release(tl);
202 return hres;
205 static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
207 HRESULT hres;
209 if (FAILED(hres = load_typelib()))
210 return hres;
212 if (!typeinfos[tid])
214 ITypeInfo *ti;
216 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
217 if (FAILED(hres)) {
218 ERR("GetTypeInfoOfGuid(%s) failed: %08lx\n", debugstr_guid(tid_ids[tid]), hres);
219 return hres;
222 if (InterlockedCompareExchangePointer((void **)(typeinfos+tid), ti, NULL))
223 ITypeInfo_Release(ti);
226 *typeinfo = typeinfos[tid];
227 ITypeInfo_AddRef(typeinfos[tid]);
228 return S_OK;
231 static void release_typelib(void)
233 unsigned i;
235 if (!typelib)
236 return;
238 for (i = 0; i < ARRAY_SIZE(typeinfos); i++)
239 if (typeinfos[i])
240 ITypeInfo_Release(typeinfos[i]);
242 ITypeLib_Release(typelib);
245 static inline struct scriptlet_global *global_from_IDispatchEx(IDispatchEx *iface)
247 return CONTAINING_RECORD(iface, struct scriptlet_global, IDispatchEx_iface);
250 static HRESULT WINAPI global_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
252 struct scriptlet_global *This = global_from_IDispatchEx(iface);
254 if (IsEqualGUID(&IID_IUnknown, riid))
256 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
257 *ppv = &This->IDispatchEx_iface;
259 else if (IsEqualGUID(&IID_IDispatch, riid))
261 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
262 *ppv = &This->IDispatchEx_iface;
264 else if (IsEqualGUID(&IID_IDispatchEx, riid))
266 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
267 *ppv = &This->IDispatchEx_iface;
269 else
271 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
272 *ppv = NULL;
273 return E_NOINTERFACE;
276 IUnknown_AddRef((IUnknown*)*ppv);
277 return S_OK;
280 static ULONG WINAPI global_AddRef(IDispatchEx *iface)
282 struct scriptlet_global *This = global_from_IDispatchEx(iface);
283 ULONG ref = InterlockedIncrement(&This->ref);
285 TRACE("(%p) ref=%ld\n", This, ref);
287 return ref;
290 static ULONG WINAPI global_Release(IDispatchEx *iface)
292 struct scriptlet_global *This = global_from_IDispatchEx(iface);
293 ULONG ref = InterlockedDecrement(&This->ref);
295 TRACE("(%p) ref=%ld\n", This, ref);
297 if (!ref) free(This);
299 return ref;
302 static HRESULT WINAPI global_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
304 struct scriptlet_global *This = global_from_IDispatchEx(iface);
305 FIXME("(%p)->(%p)\n", This, pctinfo);
306 return E_NOTIMPL;
309 static HRESULT WINAPI global_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
311 struct scriptlet_global *This = global_from_IDispatchEx(iface);
312 FIXME("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo);
313 return E_NOTIMPL;
316 static HRESULT WINAPI global_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
317 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
319 struct scriptlet_global *This = global_from_IDispatchEx(iface);
320 UINT i;
321 HRESULT hres;
323 TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
325 for(i=0; i < cNames; i++)
327 hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId + i);
328 if(FAILED(hres))
329 return hres;
332 return S_OK;
335 static HRESULT WINAPI global_Invoke(IDispatchEx *iface, DISPID dispIdMember,
336 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
337 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
339 struct scriptlet_global *This = global_from_IDispatchEx(iface);
340 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
341 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
342 return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags,
343 pDispParams, pVarResult, pExcepInfo, NULL);
346 static HRESULT WINAPI global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
348 struct scriptlet_global *This = global_from_IDispatchEx(iface);
349 FIXME("(%p)->(%s %lx %p)\n", This, debugstr_w(bstrName), grfdex, pid);
350 return E_NOTIMPL;
353 static HRESULT WINAPI global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
354 VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
356 struct scriptlet_global *This = global_from_IDispatchEx(iface);
357 FIXME("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
358 return E_NOTIMPL;
361 static HRESULT WINAPI global_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
363 struct scriptlet_global *This = global_from_IDispatchEx(iface);
364 FIXME("(%p)->(%s %lx)\n", This, debugstr_w(bstrName), grfdex);
365 return E_NOTIMPL;
368 static HRESULT WINAPI global_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
370 struct scriptlet_global *This = global_from_IDispatchEx(iface);
371 FIXME("(%p)->(%lx)\n", This, id);
372 return E_NOTIMPL;
375 static HRESULT WINAPI global_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
377 struct scriptlet_global *This = global_from_IDispatchEx(iface);
378 FIXME("(%p)->(%lx %lx %p)\n", This, id, grfdexFetch, pgrfdex);
379 return E_NOTIMPL;
382 static HRESULT WINAPI global_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
384 struct scriptlet_global *This = global_from_IDispatchEx(iface);
385 FIXME("(%p)->(%lx %p)\n", This, id, pbstrName);
386 return E_NOTIMPL;
389 static HRESULT WINAPI global_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
391 struct scriptlet_global *This = global_from_IDispatchEx(iface);
392 FIXME("(%p)->(%lx %lx %p)\n", This, grfdex, id, pid);
393 return E_NOTIMPL;
396 static HRESULT WINAPI global_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
398 struct scriptlet_global *This = global_from_IDispatchEx(iface);
399 FIXME("(%p)->(%p)\n", This, ppunk);
400 return E_NOTIMPL;
403 static IDispatchExVtbl global_vtbl = {
404 global_QueryInterface,
405 global_AddRef,
406 global_Release,
407 global_GetTypeInfoCount,
408 global_GetTypeInfo,
409 global_GetIDsOfNames,
410 global_Invoke,
411 global_GetDispID,
412 global_InvokeEx,
413 global_DeleteMemberByName,
414 global_DeleteMemberByDispID,
415 global_GetMemberProperties,
416 global_GetMemberName,
417 global_GetNextDispID,
418 global_GetNameSpaceParent
421 static HRESULT set_script_state(struct script_host *host, SCRIPTSTATE state)
423 HRESULT hres;
424 if (state == host->state) return S_OK;
425 hres = IActiveScript_SetScriptState(host->active_script, state);
426 if (FAILED(hres)) return hres;
427 host->state = state;
428 return S_OK;
431 static inline struct script_host *impl_from_IActiveScriptSite(IActiveScriptSite *iface)
433 return CONTAINING_RECORD(iface, struct script_host, IActiveScriptSite_iface);
436 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv)
438 struct script_host *This = impl_from_IActiveScriptSite(iface);
440 if (IsEqualGUID(&IID_IUnknown, riid))
442 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
443 *ppv = &This->IActiveScriptSite_iface;
445 else if (IsEqualGUID(&IID_IActiveScriptSite, riid))
447 TRACE("(%p)->(IID_IActiveScriptSite %p)\n", This, ppv);
448 *ppv = &This->IActiveScriptSite_iface;
450 else if (IsEqualGUID(&IID_IActiveScriptSiteWindow, riid))
452 TRACE("(%p)->(IID_IActiveScriptSiteWindow %p)\n", This, ppv);
453 *ppv = &This->IActiveScriptSiteWindow_iface;
455 else if(IsEqualGUID(&IID_IServiceProvider, riid))
457 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
458 *ppv = &This->IServiceProvider_iface;
460 else
462 WARN("(%p)->(%s %p) interface not supported\n", This, debugstr_guid(riid), ppv);
463 *ppv = NULL;
464 return E_NOINTERFACE;
467 IUnknown_AddRef((IUnknown*)*ppv);
468 return S_OK;
471 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
473 struct script_host *This = impl_from_IActiveScriptSite(iface);
474 LONG ref = InterlockedIncrement(&This->ref);
476 TRACE("(%p) ref=%ld\n", This, ref);
478 return ref;
481 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
483 struct script_host *This = impl_from_IActiveScriptSite(iface);
484 LONG ref = InterlockedDecrement(&This->ref);
486 TRACE("(%p) ref=%ld\n", This, ref);
488 if(!ref) {
489 free(This->language);
490 free(This);
493 return ref;
496 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *lcid)
498 struct script_host *This = impl_from_IActiveScriptSite(iface);
500 TRACE("(%p, %p)\n", This, lcid);
502 *lcid = GetUserDefaultLCID();
503 return S_OK;
506 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR name, DWORD mask,
507 IUnknown **unk, ITypeInfo **ti)
509 struct script_host *This = impl_from_IActiveScriptSite(iface);
511 TRACE("(%p, %s, %#lx, %p, %p)\n", This, debugstr_w(name), mask, unk, ti);
513 if (mask != SCRIPTINFO_IUNKNOWN)
515 FIXME("mask %lx not supported\n", mask);
516 return E_NOTIMPL;
519 if (wcscmp(name, L"scriptlet") && wcscmp(name, L"globals"))
521 FIXME("%s not supported\n", debugstr_w(name));
522 return E_FAIL;
525 if (!This->object) return E_UNEXPECTED;
527 *unk = (IUnknown *)&This->object->global->IDispatchEx_iface;
528 IUnknown_AddRef(*unk);
529 return S_OK;
532 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *version)
534 struct script_host *This = impl_from_IActiveScriptSite(iface);
535 FIXME("(%p, %p)\n", This, version);
536 return E_NOTIMPL;
539 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, const VARIANT *result,
540 const EXCEPINFO *ei)
542 struct script_host *This = impl_from_IActiveScriptSite(iface);
543 FIXME("(%p, %s, %p)\n", This, debugstr_variant(result), ei);
544 return E_NOTIMPL;
547 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE state)
549 struct script_host *This = impl_from_IActiveScriptSite(iface);
550 TRACE("(%p, %d)\n", This, state);
551 return E_NOTIMPL;
554 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *script_error)
556 struct script_host *This = impl_from_IActiveScriptSite(iface);
557 FIXME("(%p, %p)\n", This, script_error);
558 return E_NOTIMPL;
561 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface)
563 struct script_host *This = impl_from_IActiveScriptSite(iface);
564 TRACE("(%p)\n", This);
565 return S_OK;
568 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface)
570 struct script_host *This = impl_from_IActiveScriptSite(iface);
571 TRACE("(%p)\n", This);
572 return S_OK;
575 static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = {
576 ActiveScriptSite_QueryInterface,
577 ActiveScriptSite_AddRef,
578 ActiveScriptSite_Release,
579 ActiveScriptSite_GetLCID,
580 ActiveScriptSite_GetItemInfo,
581 ActiveScriptSite_GetDocVersionString,
582 ActiveScriptSite_OnScriptTerminate,
583 ActiveScriptSite_OnStateChange,
584 ActiveScriptSite_OnScriptError,
585 ActiveScriptSite_OnEnterScript,
586 ActiveScriptSite_OnLeaveScript
589 static inline struct script_host *impl_from_IActiveScriptSiteWindow(IActiveScriptSiteWindow *iface)
591 return CONTAINING_RECORD(iface, struct script_host, IActiveScriptSiteWindow_iface);
594 static HRESULT WINAPI ActiveScriptSiteWindow_QueryInterface(IActiveScriptSiteWindow *iface, REFIID riid, void **obj)
596 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
597 return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, obj);
600 static ULONG WINAPI ActiveScriptSiteWindow_AddRef(IActiveScriptSiteWindow *iface)
602 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
603 return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
606 static ULONG WINAPI ActiveScriptSiteWindow_Release(IActiveScriptSiteWindow *iface)
608 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
609 return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
612 static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *iface, HWND *hwnd)
614 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
615 FIXME("(%p, %p)\n", This, hwnd);
616 return E_NOTIMPL;
619 static HRESULT WINAPI ActiveScriptSiteWindow_EnableModeless(IActiveScriptSiteWindow *iface, BOOL enable)
621 struct script_host *This = impl_from_IActiveScriptSiteWindow(iface);
622 FIXME("(%p, %d)\n", This, enable);
623 return E_NOTIMPL;
626 static const IActiveScriptSiteWindowVtbl ActiveScriptSiteWindowVtbl = {
627 ActiveScriptSiteWindow_QueryInterface,
628 ActiveScriptSiteWindow_AddRef,
629 ActiveScriptSiteWindow_Release,
630 ActiveScriptSiteWindow_GetWindow,
631 ActiveScriptSiteWindow_EnableModeless
634 static inline struct script_host *impl_from_IServiceProvider(IServiceProvider *iface)
636 return CONTAINING_RECORD(iface, struct script_host, IServiceProvider_iface);
639 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **obj)
641 struct script_host *This = impl_from_IServiceProvider(iface);
642 return IActiveScriptSite_QueryInterface(&This->IActiveScriptSite_iface, riid, obj);
645 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
647 struct script_host *This = impl_from_IServiceProvider(iface);
648 return IActiveScriptSite_AddRef(&This->IActiveScriptSite_iface);
651 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
653 struct script_host *This = impl_from_IServiceProvider(iface);
654 return IActiveScriptSite_Release(&This->IActiveScriptSite_iface);
657 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID service,
658 REFIID riid, void **obj)
660 struct script_host *This = impl_from_IServiceProvider(iface);
661 FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(service), debugstr_guid(riid), obj);
662 return E_NOTIMPL;
665 static const IServiceProviderVtbl ServiceProviderVtbl = {
666 ServiceProvider_QueryInterface,
667 ServiceProvider_AddRef,
668 ServiceProvider_Release,
669 ServiceProvider_QueryService
672 static struct script_host *find_script_host(struct list *hosts, const WCHAR *language)
674 struct script_host *host;
675 LIST_FOR_EACH_ENTRY(host, hosts, struct script_host, entry)
677 if (!wcscmp(host->language, language)) return host;
679 return NULL;
682 static HRESULT parse_scripts(struct scriptlet_factory *factory, struct list *hosts, BOOL start)
684 DWORD parse_flags = SCRIPTTEXT_ISVISIBLE;
685 struct scriptlet_script *script;
686 struct script_host *host;
687 HRESULT hres;
689 if (!start) parse_flags |= SCRIPTITEM_ISPERSISTENT;
691 LIST_FOR_EACH_ENTRY(script, &factory->scripts, struct scriptlet_script, entry)
693 host = find_script_host(hosts, script->language);
695 if (start && host->state != SCRIPTSTATE_STARTED)
697 hres = set_script_state(host, SCRIPTSTATE_STARTED);
698 if (FAILED(hres)) return hres;
701 if (host->cloned) continue;
703 hres = IActiveScriptParse_ParseScriptText(host->parser, script->body, NULL, NULL, NULL, 0, 0 /* FIXME */,
704 parse_flags, NULL, NULL);
705 if (FAILED(hres))
707 WARN("ParseScriptText failed: %08lx\n", hres);
708 return hres;
711 if (!start)
713 LIST_FOR_EACH_ENTRY(host, hosts, struct script_host, entry)
715 if (host->state != SCRIPTSTATE_UNINITIALIZED)
716 set_script_state(host, SCRIPTSTATE_UNINITIALIZED);
719 return S_OK;
722 static HRESULT lookup_script_properties(struct scriptlet_instance *object, BSTR name, struct script_reference *ret)
724 struct script_host *host;
725 HRESULT hres;
727 LIST_FOR_EACH_ENTRY(host, &object->hosts, struct script_host, entry)
729 hres = IDispatchEx_GetDispID(host->script_dispatch, name, 0, &ret->id);
730 if (FAILED(hres)) continue;
731 ret->host = host;
732 return S_OK;
735 FIXME("Could not find %s in scripts\n", debugstr_w(name));
736 return E_FAIL;
739 static HRESULT lookup_object_properties(struct scriptlet_instance *object, struct scriptlet_factory *factory)
741 struct scriptlet_member *member;
742 unsigned i = 0, member_cnt = 0;
743 size_t len;
744 BSTR name;
745 HRESULT hres;
747 LIST_FOR_EACH_ENTRY(member, &factory->members, struct scriptlet_member, entry)
748 member_cnt++;
750 if (!member_cnt) return S_OK;
752 if (!(object->members = calloc(member_cnt, sizeof(*object->members))))
753 return E_OUTOFMEMORY;
754 object->member_cnt = member_cnt;
756 LIST_FOR_EACH_ENTRY(member, &factory->members, struct scriptlet_member, entry)
758 object->members[i].type = member->type;
759 if (!(object->members[i].name = SysAllocString(member->name))) return E_OUTOFMEMORY;
760 switch (member->type)
762 case MEMBER_METHOD:
763 hres = lookup_script_properties(object, object->members[i].name, &object->members[i].u.method);
764 if (FAILED(hres)) return hres;
765 break;
766 case MEMBER_PROPERTY:
767 len = wcslen(member->name);
768 if (!(name = SysAllocStringLen(NULL, len + 4))) return E_OUTOFMEMORY;
769 wcscpy(name, L"get_");
770 wcscat(name, member->name);
771 hres = lookup_script_properties(object, name, &object->members[i].u.property.get);
772 if (SUCCEEDED(hres))
774 memcpy(name, L"put", 3 * sizeof(WCHAR));
775 hres = lookup_script_properties(object, name, &object->members[i].u.property.put);
777 SysFreeString(name);
778 if (FAILED(hres)) return hres;
779 break;
781 i++;
784 return S_OK;
787 static HRESULT init_script_host(struct script_host *host, IActiveScript *clone)
789 HRESULT hres;
791 if (!clone)
793 IClassFactoryEx *factory_ex;
794 IClassFactory *factory;
795 IUnknown *unk;
796 CLSID clsid;
798 if (FAILED(hres = CLSIDFromProgID(host->language, &clsid)))
800 WARN("Could not find script engine for %s\n", debugstr_w(host->language));
801 return hres;
804 hres = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, NULL,
805 &IID_IClassFactory, (void**)&factory);
806 if (FAILED(hres)) return hres;
808 hres = IClassFactory_QueryInterface(factory, &IID_IClassFactoryEx, (void**)&factory_ex);
809 if (SUCCEEDED(hres))
811 FIXME("Use IClassFactoryEx\n");
812 IClassFactoryEx_Release(factory_ex);
815 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IUnknown, (void**)&unk);
816 IClassFactory_Release(factory);
817 if (FAILED(hres)) return hres;
819 hres = IUnknown_QueryInterface(unk, &IID_IActiveScript, (void**)&host->active_script);
820 IUnknown_Release(unk);
821 if (FAILED(hres)) return hres;
823 else
825 IActiveScript_AddRef(clone);
826 host->active_script = clone;
827 host->cloned = TRUE;
830 hres = IActiveScript_QueryInterface(host->active_script, &IID_IActiveScriptParse, (void**)&host->parser);
831 if (FAILED(hres)) return hres;
833 if (!clone)
835 hres = IActiveScriptParse_InitNew(host->parser);
836 if (FAILED(hres))
838 IActiveScriptParse_Release(host->parser);
839 host->parser = NULL;
840 return hres;
844 return IActiveScript_SetScriptSite(host->active_script, &host->IActiveScriptSite_iface);
847 static HRESULT create_script_host(const WCHAR *language, IActiveScript *origin_script, struct list *hosts, struct script_host **ret)
849 IActiveScript *clone = NULL;
850 struct script_host *host;
851 HRESULT hres;
853 if (!(host = calloc(1, sizeof(*host))))
854 return E_OUTOFMEMORY;
856 host->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl;
857 host->IActiveScriptSiteWindow_iface.lpVtbl = &ActiveScriptSiteWindowVtbl;
858 host->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
859 host->ref = 1;
860 host->state = SCRIPTSTATE_CLOSED;
862 if (!(host->language = wcsdup(language)))
864 IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
865 return E_OUTOFMEMORY;
868 if (origin_script)
870 hres = IActiveScript_Clone(origin_script, &clone);
871 if (FAILED(hres)) clone = NULL;
874 list_add_tail(hosts, &host->entry);
875 hres = init_script_host(host, clone);
876 if (clone) IActiveScript_Release(clone);
877 if (FAILED(hres)) return hres;
878 if (ret) *ret = host;
879 return S_OK;
882 static void detach_script_hosts(struct list *hosts)
884 while (!list_empty(hosts))
886 struct script_host *host = LIST_ENTRY(list_head(hosts), struct script_host, entry);
887 if (host->state != SCRIPTSTATE_UNINITIALIZED) set_script_state(host, SCRIPTSTATE_UNINITIALIZED);
888 list_remove(&host->entry);
889 host->object = NULL;
890 if (host->script_dispatch)
892 IDispatchEx_Release(host->script_dispatch);
893 host->script_dispatch = NULL;
895 if (host->parser)
897 IActiveScript_Close(host->active_script);
898 IActiveScriptParse_Release(host->parser);
899 host->parser = NULL;
901 if (host->active_script)
903 IActiveScript_Release(host->active_script);
904 host->active_script = NULL;
906 IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
910 static HRESULT create_scriptlet_hosts(struct scriptlet_factory *factory, struct list *hosts)
912 struct scriptlet_script *script;
913 HRESULT hres;
915 LIST_FOR_EACH_ENTRY(script, &factory->scripts, struct scriptlet_script, entry)
917 if (find_script_host(hosts, script->language)) continue;
918 hres = create_script_host(script->language, NULL, hosts, NULL);
919 if (FAILED(hres))
921 detach_script_hosts(hosts);
922 return hres;
926 return S_OK;
929 static inline struct scriptlet_instance *impl_from_IDispatchEx(IDispatchEx *iface)
931 return CONTAINING_RECORD(iface, struct scriptlet_instance, IDispatchEx_iface);
934 static HRESULT WINAPI scriptlet_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
936 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
938 if (IsEqualGUID(&IID_IUnknown, riid))
940 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
941 *ppv = &This->IDispatchEx_iface;
943 else if (IsEqualGUID(&IID_IDispatch, riid))
945 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
946 *ppv = &This->IDispatchEx_iface;
948 else if (IsEqualGUID(&IID_IDispatchEx, riid))
950 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
951 *ppv = &This->IDispatchEx_iface;
953 else
955 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
956 *ppv = NULL;
957 return E_NOINTERFACE;
960 IUnknown_AddRef((IUnknown*)*ppv);
961 return S_OK;
964 static ULONG WINAPI scriptlet_AddRef(IDispatchEx *iface)
966 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
967 ULONG ref = InterlockedIncrement(&This->ref);
969 TRACE("(%p) ref=%ld\n", This, ref);
971 return ref;
974 static ULONG WINAPI scriptlet_Release(IDispatchEx *iface)
976 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
977 ULONG ref = InterlockedDecrement(&This->ref);
979 TRACE("(%p) ref=%ld\n", This, ref);
981 if (!ref)
983 unsigned i;
984 for (i = 0; i < This->member_cnt; i++)
985 SysFreeString(This->members[i].name);
986 free(This->members);
987 detach_script_hosts(&This->hosts);
988 if (This->global) IDispatchEx_Release(&This->global->IDispatchEx_iface);
989 free(This);
991 return ref;
994 static HRESULT WINAPI scriptlet_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
996 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
997 FIXME("(%p)->(%p)\n", This, pctinfo);
998 return E_NOTIMPL;
1001 static HRESULT WINAPI scriptlet_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1003 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1004 FIXME("(%p)->(%u %lu %p)\n", This, iTInfo, lcid, ppTInfo);
1005 return E_NOTIMPL;
1008 static HRESULT WINAPI scriptlet_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
1009 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1011 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1012 UINT i;
1013 HRESULT hres;
1015 TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1016 lcid, rgDispId);
1018 for(i=0; i < cNames; i++)
1020 hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId + i);
1021 if(FAILED(hres))
1022 return hres;
1025 return S_OK;
1028 static HRESULT WINAPI scriptlet_Invoke(IDispatchEx *iface, DISPID dispIdMember,
1029 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1030 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1032 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1033 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1034 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1035 return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags,
1036 pDispParams, pVarResult, pExcepInfo, NULL);
1039 static HRESULT WINAPI scriptlet_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
1041 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1042 unsigned i;
1044 TRACE("(%p)->(%s %lx %p)\n", This, debugstr_w(bstrName), grfdex, pid);
1046 if (grfdex & ~(fdexNameCaseInsensitive|fdexNameCaseSensitive))
1047 FIXME("Unsupported grfdex %lx\n", grfdex);
1049 for (i = 0; i < This->member_cnt; i++)
1051 if (grfdex & fdexNameCaseInsensitive)
1053 if (wcsicmp(This->members[i].name, bstrName)) continue;
1055 else if (wcscmp(This->members[i].name, bstrName)) continue;
1056 *pid = i + 1;
1057 return S_OK;
1060 WARN("Unknown property %s\n", debugstr_w(bstrName));
1061 return DISP_E_UNKNOWNNAME;
1064 static HRESULT WINAPI scriptlet_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *pdp,
1065 VARIANT *res, EXCEPINFO *pei, IServiceProvider *caller)
1067 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1068 struct object_member *member;
1070 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, flags, pdp, res, pei, caller);
1072 if (id < 1 || id > This->member_cnt)
1074 WARN("Unknown id %lxu\n", id);
1075 return DISP_E_MEMBERNOTFOUND;
1077 member = &This->members[id - 1];
1079 switch (member->type)
1081 case MEMBER_METHOD:
1082 if ((flags & ~DISPATCH_PROPERTYGET) != DISPATCH_METHOD)
1084 FIXME("unsupported method flags %x\n", flags);
1085 return DISP_E_MEMBERNOTFOUND;
1087 return IDispatchEx_InvokeEx(member->u.method.host->script_dispatch, member->u.method.id, lcid,
1088 DISPATCH_METHOD, pdp, res, pei, caller);
1089 case MEMBER_PROPERTY:
1090 if (flags & DISPATCH_PROPERTYGET)
1092 if (!member->u.property.get.host)
1094 FIXME("No %s getter\n", debugstr_w(member->name));
1095 return DISP_E_MEMBERNOTFOUND;
1097 return IDispatchEx_InvokeEx(member->u.property.get.host->script_dispatch, member->u.property.get.id, lcid,
1098 DISPATCH_METHOD, pdp, res, pei, caller);
1100 if (flags & DISPATCH_PROPERTYPUT)
1102 DISPPARAMS dp;
1104 if (!member->u.property.put.host)
1106 FIXME("No %s setter\n", debugstr_w(member->name));
1107 return DISP_E_MEMBERNOTFOUND;
1109 if (pdp->cNamedArgs != 1 || pdp->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)
1111 FIXME("no propput argument\n");
1112 return E_FAIL;
1114 dp = *pdp;
1115 dp.cNamedArgs = 0;
1116 return IDispatchEx_InvokeEx(member->u.property.put.host->script_dispatch, member->u.property.put.id, lcid,
1117 DISPATCH_METHOD, &dp, res, pei, caller);
1120 FIXME("unsupported flags %x\n", flags);
1123 return DISP_E_MEMBERNOTFOUND;
1126 static HRESULT WINAPI scriptlet_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
1128 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1129 FIXME("(%p)->(%s %lx)\n", This, debugstr_w(bstrName), grfdex);
1130 return E_NOTIMPL;
1133 static HRESULT WINAPI scriptlet_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
1135 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1136 FIXME("(%p)->(%lx)\n", This, id);
1137 return E_NOTIMPL;
1140 static HRESULT WINAPI scriptlet_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
1142 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1143 FIXME("(%p)->(%lx %lx %p)\n", This, id, grfdexFetch, pgrfdex);
1144 return E_NOTIMPL;
1147 static HRESULT WINAPI scriptlet_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
1149 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1150 FIXME("(%p)->(%lx %p)\n", This, id, pbstrName);
1151 return E_NOTIMPL;
1154 static HRESULT WINAPI scriptlet_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
1156 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1157 FIXME("(%p)->(%lx %lx %p)\n", This, grfdex, id, pid);
1158 return E_NOTIMPL;
1161 static HRESULT WINAPI scriptlet_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
1163 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1164 FIXME("(%p)->(%p)\n", This, ppunk);
1165 return E_NOTIMPL;
1168 static IDispatchExVtbl DispatchExVtbl = {
1169 scriptlet_QueryInterface,
1170 scriptlet_AddRef,
1171 scriptlet_Release,
1172 scriptlet_GetTypeInfoCount,
1173 scriptlet_GetTypeInfo,
1174 scriptlet_GetIDsOfNames,
1175 scriptlet_Invoke,
1176 scriptlet_GetDispID,
1177 scriptlet_InvokeEx,
1178 scriptlet_DeleteMemberByName,
1179 scriptlet_DeleteMemberByDispID,
1180 scriptlet_GetMemberProperties,
1181 scriptlet_GetMemberName,
1182 scriptlet_GetNextDispID,
1183 scriptlet_GetNameSpaceParent
1186 static HRESULT create_scriptlet_instance(struct scriptlet_factory *factory, IDispatchEx **disp)
1188 struct script_host *factory_host, *host;
1189 struct scriptlet_instance *obj;
1190 IDispatch *script_dispatch;
1191 HRESULT hres = S_OK;
1193 if (!(obj = calloc(1, sizeof(*obj))))
1194 return E_OUTOFMEMORY;
1196 obj->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
1197 obj->ref = 1;
1198 list_init(&obj->hosts);
1200 if (!(obj->global = malloc(sizeof(*obj->global))))
1202 IDispatchEx_Release(&obj->IDispatchEx_iface);
1203 return E_OUTOFMEMORY;
1205 obj->global->IDispatchEx_iface.lpVtbl = &global_vtbl;
1206 obj->global->ref = 1;
1208 LIST_FOR_EACH_ENTRY(factory_host, &factory->hosts, struct script_host, entry)
1210 hres = create_script_host(factory_host->language, factory_host->active_script, &obj->hosts, &host);
1211 if (FAILED(hres)) break;
1212 host->object = obj;
1214 hres = IActiveScript_AddNamedItem(host->active_script, L"scriptlet",
1215 SCRIPTITEM_ISVISIBLE | SCRIPTITEM_GLOBALMEMBERS);
1216 if (FAILED(hres)) break;
1218 hres = IActiveScript_AddNamedItem(host->active_script, L"globals", SCRIPTITEM_ISVISIBLE);
1219 if (FAILED(hres)) break;
1221 hres = IActiveScript_GetScriptDispatch(host->active_script, NULL, &script_dispatch);
1222 if (FAILED(hres)) return hres;
1224 hres = IDispatch_QueryInterface(script_dispatch, &IID_IDispatchEx, (void**)&host->script_dispatch);
1225 IDispatch_Release(script_dispatch);
1226 if (FAILED(hres))
1228 FIXME("IDispatchEx not supported by script engine\n");
1229 return hres;
1233 if (SUCCEEDED(hres)) hres = parse_scripts(factory, &obj->hosts, TRUE);
1234 if (SUCCEEDED(hres)) hres = lookup_object_properties(obj, factory);
1235 if (FAILED(hres))
1237 IDispatchEx_Release(&obj->IDispatchEx_iface);
1238 return hres;
1241 *disp = &obj->IDispatchEx_iface;
1242 return S_OK;
1245 static const char *debugstr_xml_name(struct scriptlet_factory *factory)
1247 const WCHAR *str;
1248 UINT len;
1249 HRESULT hres;
1250 hres = IXmlReader_GetLocalName(factory->xml_reader, &str, &len);
1251 if (FAILED(hres)) return "#err";
1252 return debugstr_wn(str, len);
1255 static HRESULT next_xml_node(struct scriptlet_factory *factory, XmlNodeType *node_type)
1257 HRESULT hres;
1258 for (;;)
1260 hres = IXmlReader_Read(factory->xml_reader, node_type);
1261 if (FAILED(hres)) break;
1262 if (*node_type == XmlNodeType_Whitespace) continue;
1263 if (*node_type == XmlNodeType_ProcessingInstruction)
1265 FIXME("Ignoring processing instruction\n");
1266 continue;
1268 break;
1270 return hres;
1273 static BOOL is_xml_name(struct scriptlet_factory *factory, const WCHAR *name)
1275 const WCHAR *qname;
1276 UINT len;
1277 HRESULT hres;
1278 hres = IXmlReader_GetQualifiedName(factory->xml_reader, &qname, &len);
1279 return hres == S_OK && len == wcslen(name) && !memcmp(qname, name, len * sizeof(WCHAR));
1282 static HRESULT expect_end_element(struct scriptlet_factory *factory)
1284 XmlNodeType node_type;
1285 HRESULT hres;
1286 hres = next_xml_node(factory, &node_type);
1287 if (hres != S_OK || node_type != XmlNodeType_EndElement)
1289 FIXME("Unexpected node %u %s\n", node_type, debugstr_xml_name(factory));
1290 return E_FAIL;
1292 return S_OK;
1295 static HRESULT expect_no_attributes(struct scriptlet_factory *factory)
1297 UINT count;
1298 HRESULT hres;
1299 hres = IXmlReader_GetAttributeCount(factory->xml_reader, &count);
1300 if (FAILED(hres)) return hres;
1301 if (!count) return S_OK;
1302 FIXME("Unexpected attributes\n");
1303 return E_FAIL;
1306 static BOOL is_case_xml_name(struct scriptlet_factory *factory, const WCHAR *name)
1308 const WCHAR *qname;
1309 UINT len;
1310 HRESULT hres;
1311 hres = IXmlReader_GetQualifiedName(factory->xml_reader, &qname, &len);
1312 return hres == S_OK && len == wcslen(name) && !memicmp(qname, name, len * sizeof(WCHAR));
1315 static HRESULT read_xml_value(struct scriptlet_factory *factory, WCHAR **ret)
1317 const WCHAR *str;
1318 UINT len;
1319 HRESULT hres;
1320 hres = IXmlReader_GetValue(factory->xml_reader, &str, &len);
1321 if (FAILED(hres)) return hres;
1322 if (!(*ret = malloc((len + 1) * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1323 memcpy(*ret, str, len * sizeof(WCHAR));
1324 (*ret)[len] = 0;
1325 return S_OK;
1328 static HRESULT parse_scriptlet_registration(struct scriptlet_factory *factory)
1330 HRESULT hres;
1332 TRACE("\n");
1334 if (factory->have_registration)
1336 FIXME("duplicated registration element\n");
1337 return E_FAIL;
1339 factory->have_registration = TRUE;
1341 for (;;)
1343 hres = IXmlReader_MoveToNextAttribute(factory->xml_reader);
1344 if (hres != S_OK) break;
1346 if (is_xml_name(factory, L"description"))
1348 if (factory->description)
1350 FIXME("Duplicated description\n");
1351 return E_FAIL;
1353 hres = read_xml_value(factory, &factory->description);
1354 if (FAILED(hres)) return hres;
1356 else if (is_case_xml_name(factory, L"progid"))
1358 if (factory->progid)
1360 FIXME("Duplicated progid\n");
1361 return E_FAIL;
1363 hres = read_xml_value(factory, &factory->progid);
1364 if (FAILED(hres)) return hres;
1366 else if (is_xml_name(factory, L"version"))
1368 if (factory->version)
1370 FIXME("Duplicated version\n");
1371 return E_FAIL;
1373 hres = read_xml_value(factory, &factory->version);
1374 if (FAILED(hres)) return hres;
1376 else if (is_xml_name(factory, L"classid"))
1378 if (factory->classid_str)
1380 FIXME("Duplicated classid attribute\n");
1381 return E_FAIL;
1383 hres = read_xml_value(factory, &factory->classid_str);
1384 if (FAILED(hres)) return hres;
1385 hres = IIDFromString(factory->classid_str, &factory->classid);
1386 if (FAILED(hres))
1388 FIXME("Invalid classid %s\n", debugstr_w(factory->classid_str));
1390 return E_FAIL;
1393 else
1395 FIXME("Unexpected attribute\n");
1396 return E_NOTIMPL;
1400 if (!factory->progid && !factory->classid_str)
1402 FIXME("Incomplet registration element\n");
1403 return E_FAIL;
1406 if (factory->progid)
1408 size_t progid_len = wcslen(factory->progid);
1409 size_t version_len = wcslen(factory->version);
1411 if (!(factory->versioned_progid = malloc((progid_len + version_len + 2) * sizeof(WCHAR))))
1412 return E_OUTOFMEMORY;
1414 memcpy(factory->versioned_progid, factory->progid, (progid_len + 1) * sizeof(WCHAR));
1415 if (version_len)
1417 factory->versioned_progid[progid_len++] = '.';
1418 wcscpy(factory->versioned_progid + progid_len, factory->version);
1420 else factory->versioned_progid[progid_len] = 0;
1423 return expect_end_element(factory);
1426 static HRESULT parse_scriptlet_public(struct scriptlet_factory *factory)
1428 struct scriptlet_member *member, *member_iter;
1429 enum member_type member_type;
1430 XmlNodeType node_type;
1431 BOOL empty;
1432 HRESULT hres;
1434 TRACE("\n");
1436 if (factory->have_public)
1438 FIXME("duplicated public element\n");
1439 return E_FAIL;
1441 factory->have_public = TRUE;
1443 for (;;)
1445 hres = next_xml_node(factory, &node_type);
1446 if (FAILED(hres)) return hres;
1447 if (node_type == XmlNodeType_EndElement) break;
1448 if (node_type != XmlNodeType_Element)
1450 FIXME("Unexpected node type %u\n", node_type);
1451 return E_FAIL;
1454 if (is_xml_name(factory, L"method"))
1455 member_type = MEMBER_METHOD;
1456 else if (is_xml_name(factory, L"property"))
1457 member_type = MEMBER_PROPERTY;
1458 else
1460 FIXME("Unexpected element %s\n", debugstr_xml_name(factory));
1461 return E_NOTIMPL;
1464 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1466 hres = IXmlReader_MoveToAttributeByName(factory->xml_reader, L"name", NULL);
1467 if (hres != S_OK)
1469 FIXME("Missing method name\n");
1470 return E_FAIL;
1473 if (!(member = malloc(sizeof(*member)))) return E_OUTOFMEMORY;
1474 member->type = member_type;
1476 hres = read_xml_value(factory, &member->name);
1477 if (FAILED(hres))
1479 free(member);
1480 return hres;
1483 LIST_FOR_EACH_ENTRY(member_iter, &factory->members, struct scriptlet_member, entry)
1485 if (!wcsicmp(member_iter->name, member->name))
1487 FIXME("Duplicated member %s\n", debugstr_w(member->name));
1488 free(member);
1489 return E_FAIL;
1492 list_add_tail(&factory->members, &member->entry);
1494 switch (member_type)
1496 case MEMBER_METHOD:
1497 list_init(&member->u.parameters);
1499 if (empty) break;
1500 for (;;)
1502 struct method_parameter *parameter;
1504 hres = next_xml_node(factory, &node_type);
1505 if (FAILED(hres)) return hres;
1506 if (node_type == XmlNodeType_EndElement) break;
1507 if (node_type != XmlNodeType_Element)
1509 FIXME("Unexpected node type %u\n", node_type);
1510 return E_FAIL;
1512 if (!is_case_xml_name(factory, L"parameter"))
1514 FIXME("Unexpected method element\n");
1515 return E_FAIL;
1518 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1520 hres = IXmlReader_MoveToAttributeByName(factory->xml_reader, L"name", NULL);
1521 if (hres != S_OK)
1523 FIXME("Missing parameter name\n");
1524 return E_FAIL;
1527 if (!(parameter = calloc(1, sizeof(*parameter)))) return E_OUTOFMEMORY;
1528 list_add_tail(&member->u.parameters, &parameter->entry);
1530 hres = read_xml_value(factory, &parameter->name);
1531 if (FAILED(hres)) return hres;
1532 if (!empty && FAILED(hres = expect_end_element(factory))) return hres;
1534 break;
1536 case MEMBER_PROPERTY:
1537 member->u.flags = 0;
1539 if (empty) break;
1540 for (;;)
1542 hres = next_xml_node(factory, &node_type);
1543 if (FAILED(hres)) return hres;
1544 if (node_type == XmlNodeType_EndElement) break;
1545 if (node_type != XmlNodeType_Element)
1547 FIXME("Unexpected node type %u\n", node_type);
1548 return E_FAIL;
1550 if (is_case_xml_name(factory, L"get"))
1552 if (member->u.flags & PROP_GETTER)
1554 FIXME("Duplicated getter\n");
1555 return E_FAIL;
1557 member->u.flags |= PROP_GETTER;
1559 else if (is_case_xml_name(factory, L"put"))
1561 if (member->u.flags & PROP_SETTER)
1563 FIXME("Duplicated setter\n");
1564 return E_FAIL;
1566 member->u.flags |= PROP_SETTER;
1568 else
1570 FIXME("Unexpected property element %s\n", debugstr_xml_name(factory));
1571 return E_FAIL;
1574 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1575 if (!empty && FAILED(hres = expect_end_element(factory))) return hres;
1577 if (!member->u.flags)
1579 FIXME("No getter or setter\n");
1580 return E_NOTIMPL;
1582 break;
1584 if (FAILED(hres)) return hres;
1587 return S_OK;
1590 static HRESULT parse_scriptlet_script(struct scriptlet_factory *factory, struct scriptlet_script *script)
1592 XmlNodeType node_type;
1593 size_t buf_size, size;
1594 WCHAR *new_body;
1595 UINT read;
1596 HRESULT hres;
1598 TRACE("\n");
1600 for (;;)
1602 hres = IXmlReader_MoveToNextAttribute(factory->xml_reader);
1603 if (hres != S_OK) break;
1605 if (is_xml_name(factory, L"language"))
1607 if (script->language)
1609 FIXME("Duplicated language\n");
1610 return E_FAIL;
1612 hres = read_xml_value(factory, &script->language);
1613 if (FAILED(hres)) return hres;
1615 else
1617 FIXME("Unexpected attribute\n");
1618 return E_NOTIMPL;
1622 if (!script->language)
1624 FIXME("Language not specified\n");
1625 return E_FAIL;
1628 if (FAILED(hres = next_xml_node(factory, &node_type))) return hres;
1630 if (node_type != XmlNodeType_Text && node_type != XmlNodeType_CDATA)
1632 FIXME("Unexpected node type %u\n", node_type);
1633 return E_FAIL;
1636 if (!(script->body = malloc((buf_size = 1024) * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1637 size = 0;
1639 for (;;)
1641 read = 0;
1642 hres = IXmlReader_ReadValueChunk(factory->xml_reader, script->body + size, buf_size - size - 1, &read);
1643 if (FAILED(hres)) return hres;
1644 size += read;
1645 if (hres == S_FALSE) break;
1646 if (size + 1 == buf_size)
1648 if (!(new_body = realloc(script->body, (buf_size *= 2) * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1649 script->body = new_body;
1652 script->body[size++] = 0;
1653 if (size != buf_size) script->body = realloc(script->body, size * sizeof(WCHAR));
1655 TRACE("body %s\n", debugstr_w(script->body));
1656 return expect_end_element(factory);
1659 static HRESULT parse_scriptlet_file(struct scriptlet_factory *factory, const WCHAR *url)
1661 XmlNodeType node_type;
1662 IBindCtx *bind_ctx;
1663 IStream *stream;
1664 HRESULT hres;
1666 hres = CreateURLMoniker(NULL, url, &factory->moniker);
1667 if (FAILED(hres))
1669 WARN("CreateURLMoniker failed: %08lx\n", hres);
1670 return hres;
1673 hres = CreateBindCtx(0, &bind_ctx);
1674 if(FAILED(hres))
1675 return hres;
1677 hres = IMoniker_BindToStorage(factory->moniker, bind_ctx, NULL, &IID_IStream, (void**)&stream);
1678 IBindCtx_Release(bind_ctx);
1679 if (FAILED(hres))
1680 return hres;
1682 hres = CreateXmlReader(&IID_IXmlReader, (void**)&factory->xml_reader, NULL);
1683 if(SUCCEEDED(hres))
1684 hres = IXmlReader_SetInput(factory->xml_reader, (IUnknown*)stream);
1685 IStream_Release(stream);
1686 if (FAILED(hres))
1687 return hres;
1689 hres = next_xml_node(factory, &node_type);
1690 if (hres == S_OK && node_type == XmlNodeType_XmlDeclaration)
1691 hres = next_xml_node(factory, &node_type);
1692 if (FAILED(hres))
1693 return hres;
1695 if (node_type != XmlNodeType_Element || !is_xml_name(factory, L"component"))
1697 FIXME("Unexpected %s element\n", debugstr_xml_name(factory));
1698 return E_FAIL;
1701 hres = expect_no_attributes(factory);
1702 if (FAILED(hres)) return hres;
1704 for (;;)
1706 hres = next_xml_node(factory, &node_type);
1707 if (FAILED(hres)) return hres;
1708 if (node_type == XmlNodeType_EndElement) break;
1709 if (node_type != XmlNodeType_Element)
1711 FIXME("Unexpected node type %u\n", node_type);
1712 return E_FAIL;
1715 if (is_xml_name(factory, L"registration"))
1716 hres = parse_scriptlet_registration(factory);
1717 else if (is_xml_name(factory, L"public"))
1718 hres = parse_scriptlet_public(factory);
1719 else if (is_xml_name(factory, L"script"))
1721 struct scriptlet_script *script;
1722 if (!(script = calloc(1, sizeof(*script)))) return E_OUTOFMEMORY;
1723 list_add_tail(&factory->scripts, &script->entry);
1724 hres = parse_scriptlet_script(factory, script);
1725 if (FAILED(hres)) return hres;
1727 else
1729 FIXME("Unexpected element %s\n", debugstr_xml_name(factory));
1730 return E_NOTIMPL;
1732 if (FAILED(hres)) return hres;
1735 hres = next_xml_node(factory, &node_type);
1736 if (hres != S_FALSE)
1738 FIXME("Unexpected node type %u\n", node_type);
1739 return E_FAIL;
1741 return S_OK;
1744 static inline struct scriptlet_factory *impl_from_IClassFactory(IClassFactory *iface)
1746 return CONTAINING_RECORD(iface, struct scriptlet_factory, IClassFactory_iface);
1749 static HRESULT WINAPI scriptlet_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
1751 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1753 if (IsEqualGUID(&IID_IUnknown, riid))
1755 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
1756 *ppv = &This->IClassFactory_iface;
1758 else if (IsEqualGUID(&IID_IClassFactory, riid))
1760 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
1761 *ppv = &This->IClassFactory_iface;
1763 else
1765 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
1766 *ppv = NULL;
1767 return E_NOINTERFACE;
1770 IUnknown_AddRef((IUnknown *)*ppv);
1771 return S_OK;
1774 static ULONG WINAPI scriptlet_factory_AddRef(IClassFactory *iface)
1776 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1777 ULONG ref = InterlockedIncrement(&This->ref);
1779 TRACE("(%p) ref=%ld\n", This, ref);
1781 return ref;
1784 static ULONG WINAPI scriptlet_factory_Release(IClassFactory *iface)
1786 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1787 ULONG ref = InterlockedDecrement(&This->ref);
1789 TRACE("(%p) ref=%ld\n", This, ref);
1791 if (!ref)
1793 if (This->moniker) IMoniker_Release(This->moniker);
1794 if (This->xml_reader) IXmlReader_Release(This->xml_reader);
1795 detach_script_hosts(&This->hosts);
1796 while (!list_empty(&This->members))
1798 struct scriptlet_member *member = LIST_ENTRY(list_head(&This->members), struct scriptlet_member, entry);
1799 list_remove(&member->entry);
1800 free(member->name);
1801 if (member->type == MEMBER_METHOD)
1803 while (!list_empty(&member->u.parameters))
1805 struct method_parameter *parameter = LIST_ENTRY(list_head(&member->u.parameters), struct method_parameter, entry);
1806 list_remove(&parameter->entry);
1807 free(parameter->name);
1808 free(parameter);
1811 free(member);
1813 while (!list_empty(&This->scripts))
1815 struct scriptlet_script *script = LIST_ENTRY(list_head(&This->scripts), struct scriptlet_script, entry);
1816 list_remove(&script->entry);
1817 free(script->language);
1818 free(script->body);
1819 free(script);
1821 free(This->classid_str);
1822 free(This->description);
1823 free(This->versioned_progid);
1824 free(This->progid);
1825 free(This->version);
1826 free(This);
1828 return ref;
1831 static HRESULT WINAPI scriptlet_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1833 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1834 IDispatchEx *disp;
1835 HRESULT hres;
1837 TRACE("(%p)->(%p %s %p)\n", This, outer, debugstr_guid(riid), ppv);
1839 if (outer) FIXME("outer not supported\n");
1841 if (list_empty(&This->hosts))
1843 hres = create_scriptlet_hosts(This, &This->hosts);
1844 if (FAILED(hres)) return hres;
1846 hres = parse_scripts(This, &This->hosts, FALSE);
1847 if (FAILED(hres))
1849 detach_script_hosts(&This->hosts);
1850 return hres;
1854 hres = create_scriptlet_instance(This, &disp);
1855 if (FAILED(hres)) return hres;
1857 hres = IDispatchEx_QueryInterface(disp, riid, ppv);
1858 IDispatchEx_Release(disp);
1859 return hres;
1862 static HRESULT WINAPI scriptlet_factory_LockServer(IClassFactory *iface, BOOL fLock)
1864 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1865 TRACE("(%p)->(%x)\n", This, fLock);
1866 return S_OK;
1869 static const struct IClassFactoryVtbl scriptlet_factory_vtbl =
1871 scriptlet_factory_QueryInterface,
1872 scriptlet_factory_AddRef,
1873 scriptlet_factory_Release,
1874 scriptlet_factory_CreateInstance,
1875 scriptlet_factory_LockServer
1878 static HRESULT create_scriptlet_factory(const WCHAR *url, struct scriptlet_factory **ret)
1880 struct scriptlet_factory *factory;
1881 HRESULT hres;
1883 TRACE("%s\n", debugstr_w(url));
1885 if (!(factory = calloc(1, sizeof(*factory))))
1886 return E_OUTOFMEMORY;
1888 factory->IClassFactory_iface.lpVtbl = &scriptlet_factory_vtbl;
1889 factory->ref = 1;
1890 list_init(&factory->hosts);
1891 list_init(&factory->members);
1892 list_init(&factory->scripts);
1894 hres = parse_scriptlet_file(factory, url);
1895 if (FAILED(hres))
1897 IClassFactory_Release(&factory->IClassFactory_iface);
1898 return hres;
1901 *ret = factory;
1902 return S_OK;
1905 static HRESULT register_scriptlet(struct scriptlet_factory *factory)
1907 HKEY key, clsid_key, obj_key;
1908 LSTATUS status;
1909 HRESULT hres;
1911 if (factory->classid_str)
1913 WCHAR *url;
1915 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"CLSID", &clsid_key);
1916 if (status) return E_ACCESSDENIED;
1918 status = RegCreateKeyW(clsid_key, factory->classid_str, &obj_key);
1919 RegCloseKey(clsid_key);
1920 if (status) return E_ACCESSDENIED;
1922 hres = IMoniker_GetDisplayName(factory->moniker, NULL, NULL, &url);
1923 if (FAILED(hres))
1925 RegCloseKey(obj_key);
1926 return hres;
1928 status = RegCreateKeyW(obj_key, L"ScriptletURL", &key);
1929 if (!status)
1931 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)url,
1932 (wcslen(url) + 1) * sizeof(WCHAR));
1933 RegCloseKey(key);
1935 CoTaskMemFree(url);
1937 if (factory->description)
1938 status = RegSetValueExW(obj_key, NULL, 0, REG_SZ, (BYTE*)factory->description,
1939 (wcslen(factory->description) + 1) * sizeof(WCHAR));
1941 if (!status)
1943 status = RegCreateKeyW(obj_key, L"InprocServer32", &key);
1944 if (!status)
1946 WCHAR str[MAX_PATH];
1947 GetModuleFileNameW(scrobj_instance, str, MAX_PATH);
1948 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)str, (wcslen(str) + 1) * sizeof(WCHAR));
1949 RegCloseKey(key);
1953 if (!status && factory->versioned_progid)
1955 status = RegCreateKeyW(obj_key, L"ProgID", &key);
1956 if (!status)
1958 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->versioned_progid,
1959 (wcslen(factory->versioned_progid) + 1) * sizeof(WCHAR));
1960 RegCloseKey(key);
1964 if (!status && factory->progid)
1966 status = RegCreateKeyW(obj_key, L"VersionIndependentProgID", &key);
1967 if (!status)
1969 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->progid,
1970 (wcslen(factory->progid) + 1) * sizeof(WCHAR));
1971 RegCloseKey(key);
1975 RegCloseKey(obj_key);
1976 if (status) return E_ACCESSDENIED;
1979 if (factory->progid)
1981 status = RegCreateKeyW(HKEY_CLASSES_ROOT, factory->progid, &key);
1982 if (status) return E_ACCESSDENIED;
1984 if (factory->description)
1985 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->description,
1986 (wcslen(factory->description) + 1) * sizeof(WCHAR));
1988 if (!status && factory->classid_str)
1990 status = RegCreateKeyW(key, L"CLSID", &clsid_key);
1991 if (!status)
1993 status = RegSetValueExW(clsid_key, NULL, 0, REG_SZ, (BYTE*)factory->classid_str,
1994 (wcslen(factory->classid_str) + 1) * sizeof(WCHAR));
1995 RegCloseKey(clsid_key);
1999 RegCloseKey(key);
2000 if (status) return E_ACCESSDENIED;
2003 if (factory->versioned_progid)
2005 status = RegCreateKeyW(HKEY_CLASSES_ROOT, factory->versioned_progid, &key);
2006 if (status) return E_ACCESSDENIED;
2008 if (factory->description)
2009 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->description,
2010 (wcslen(factory->description) + 1) * sizeof(WCHAR));
2012 if (!status && factory->classid_str)
2014 status = RegCreateKeyW(key, L"CLSID", &clsid_key);
2015 if (!status)
2017 status = RegSetValueExW(clsid_key, NULL, 0, REG_SZ, (BYTE*)factory->classid_str,
2018 (wcslen(factory->classid_str) + 1) * sizeof(WCHAR));
2019 RegCloseKey(clsid_key);
2023 RegCloseKey(key);
2024 if (status) return E_ACCESSDENIED;
2027 return S_OK;
2030 static HRESULT unregister_scriptlet(struct scriptlet_factory *factory)
2032 LSTATUS status;
2034 if (factory->classid_str)
2036 HKEY clsid_key;
2037 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"CLSID", &clsid_key);
2038 if (!status)
2040 RegDeleteTreeW(clsid_key, factory->classid_str);
2041 RegCloseKey(clsid_key);
2045 if (factory->progid) RegDeleteTreeW(HKEY_CLASSES_ROOT, factory->progid);
2046 if (factory->versioned_progid) RegDeleteTreeW(HKEY_CLASSES_ROOT, factory->versioned_progid);
2047 return S_OK;
2050 struct scriptlet_typelib
2052 IGenScriptletTLib IGenScriptletTLib_iface;
2053 LONG ref;
2055 BSTR guid;
2058 static inline struct scriptlet_typelib *impl_from_IGenScriptletTLib(IGenScriptletTLib *iface)
2060 return CONTAINING_RECORD(iface, struct scriptlet_typelib, IGenScriptletTLib_iface);
2063 static HRESULT WINAPI scriptlet_typelib_QueryInterface(IGenScriptletTLib *iface, REFIID riid, void **obj)
2065 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2067 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), obj);
2069 if (IsEqualIID(riid, &IID_IGenScriptletTLib) ||
2070 IsEqualIID(riid, &IID_IDispatch) ||
2071 IsEqualIID(riid, &IID_IUnknown))
2073 *obj = iface;
2074 IGenScriptletTLib_AddRef(iface);
2075 return S_OK;
2078 *obj = NULL;
2079 return E_NOINTERFACE;
2082 static ULONG WINAPI scriptlet_typelib_AddRef(IGenScriptletTLib *iface)
2084 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2085 ULONG ref = InterlockedIncrement(&This->ref);
2086 TRACE("(%p)->(%lu)\n", This, ref);
2087 return ref;
2090 static ULONG WINAPI scriptlet_typelib_Release(IGenScriptletTLib *iface)
2092 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2093 LONG ref = InterlockedDecrement(&This->ref);
2095 TRACE("(%p)->(%lu)\n", This, ref);
2097 if (!ref)
2099 SysFreeString(This->guid);
2100 free(This);
2103 return ref;
2106 static HRESULT WINAPI scriptlet_typelib_GetTypeInfoCount(IGenScriptletTLib *iface, UINT *count)
2108 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2110 TRACE("(%p, %p)\n", This, count);
2112 *count = 1;
2113 return S_OK;
2116 static HRESULT WINAPI scriptlet_typelib_GetTypeInfo(IGenScriptletTLib *iface, UINT index, LCID lcid,
2117 ITypeInfo **tinfo)
2119 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2121 TRACE("(%p, %u, %lx, %p)\n", This, index, lcid, tinfo);
2123 return get_typeinfo(IGenScriptletTLib_tid, tinfo);
2126 static HRESULT WINAPI scriptlet_typelib_GetIDsOfNames(IGenScriptletTLib *iface, REFIID riid, LPOLESTR *names,
2127 UINT cNames, LCID lcid, DISPID *dispid)
2129 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2130 ITypeInfo *typeinfo;
2131 HRESULT hr;
2133 TRACE("(%p, %s, %p, %u, %lx, %p)\n", This, debugstr_guid(riid), names, cNames, lcid, dispid);
2135 hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo);
2136 if (SUCCEEDED(hr))
2138 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, cNames, dispid);
2139 ITypeInfo_Release(typeinfo);
2142 return hr;
2145 static HRESULT WINAPI scriptlet_typelib_Invoke(IGenScriptletTLib *iface, DISPID dispid, REFIID riid,
2146 LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *ei, UINT *argerr)
2148 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2149 ITypeInfo *typeinfo;
2150 HRESULT hr;
2152 TRACE("(%p, %ld, %s, %lx, %x, %p, %p, %p, %p)\n", This, dispid, debugstr_guid(riid), lcid, flags,
2153 params, result, ei, argerr);
2155 hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo);
2156 if (SUCCEEDED(hr))
2158 hr = ITypeInfo_Invoke(typeinfo, &This->IGenScriptletTLib_iface, dispid, flags,
2159 params, result, ei, argerr);
2160 ITypeInfo_Release(typeinfo);
2163 return hr;
2166 static HRESULT WINAPI scriptlet_typelib_AddURL(IGenScriptletTLib *iface, BSTR url)
2168 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2170 FIXME("(%p, %s): stub\n", This, debugstr_w(url));
2172 return E_NOTIMPL;
2175 static HRESULT WINAPI scriptlet_typelib_put_Path(IGenScriptletTLib *iface, BSTR path)
2177 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2179 FIXME("(%p, %s): stub\n", This, debugstr_w(path));
2181 return E_NOTIMPL;
2184 static HRESULT WINAPI scriptlet_typelib_get_Path(IGenScriptletTLib *iface, BSTR *path)
2186 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2188 FIXME("(%p, %p): stub\n", This, path);
2190 return E_NOTIMPL;
2193 static HRESULT WINAPI scriptlet_typelib_put_Doc(IGenScriptletTLib *iface, BSTR doc)
2195 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2197 FIXME("(%p, %s): stub\n", This, debugstr_w(doc));
2199 return E_NOTIMPL;
2202 static HRESULT WINAPI scriptlet_typelib_get_Doc(IGenScriptletTLib *iface, BSTR *doc)
2204 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2206 FIXME("(%p, %p): stub\n", This, doc);
2208 return E_NOTIMPL;
2211 static HRESULT WINAPI scriptlet_typelib_put_Name(IGenScriptletTLib *iface, BSTR name)
2213 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2215 FIXME("(%p, %s): stub\n", This, debugstr_w(name));
2217 return E_NOTIMPL;
2220 static HRESULT WINAPI scriptlet_typelib_get_Name(IGenScriptletTLib *iface, BSTR *name)
2222 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2224 FIXME("(%p, %p): stub\n", This, name);
2226 return E_NOTIMPL;
2229 static HRESULT WINAPI scriptlet_typelib_put_MajorVersion(IGenScriptletTLib *iface, WORD version)
2231 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2233 FIXME("(%p, %x): stub\n", This, version);
2235 return E_NOTIMPL;
2238 static HRESULT WINAPI scriptlet_typelib_get_MajorVersion(IGenScriptletTLib *iface, WORD *version)
2240 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2242 FIXME("(%p, %p): stub\n", This, version);
2244 return E_NOTIMPL;
2247 static HRESULT WINAPI scriptlet_typelib_put_MinorVersion(IGenScriptletTLib *iface, WORD version)
2249 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2251 FIXME("(%p, %x): stub\n", This, version);
2253 return E_NOTIMPL;
2256 static HRESULT WINAPI scriptlet_typelib_get_MinorVersion(IGenScriptletTLib *iface, WORD *version)
2258 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2260 FIXME("(%p, %p): stub\n", This, version);
2262 return E_NOTIMPL;
2265 static HRESULT WINAPI scriptlet_typelib_Write(IGenScriptletTLib *iface)
2267 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2269 FIXME("(%p): stub\n", This);
2271 return E_NOTIMPL;
2274 static HRESULT WINAPI scriptlet_typelib_Reset(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_put_GUID(IGenScriptletTLib *iface, BSTR guid)
2285 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2287 FIXME("(%p, %s): stub\n", This, debugstr_w(guid));
2289 return E_NOTIMPL;
2292 static HRESULT WINAPI scriptlet_typelib_get_GUID(IGenScriptletTLib *iface, BSTR *ret)
2294 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2296 TRACE("(%p, %p)\n", This, ret);
2298 *ret = NULL;
2300 if (!This->guid)
2302 WCHAR guidW[39];
2303 GUID guid;
2304 HRESULT hr;
2306 hr = CoCreateGuid(&guid);
2307 if (FAILED(hr))
2308 return hr;
2310 hr = StringFromGUID2(&guid, guidW, ARRAY_SIZE(guidW));
2311 if (FAILED(hr))
2312 return hr;
2314 if (!(This->guid = SysAllocString(guidW)))
2315 return E_OUTOFMEMORY;
2318 *ret = SysAllocString(This->guid);
2319 return *ret ? S_OK : E_OUTOFMEMORY;
2322 static const IGenScriptletTLibVtbl scriptlet_typelib_vtbl =
2324 scriptlet_typelib_QueryInterface,
2325 scriptlet_typelib_AddRef,
2326 scriptlet_typelib_Release,
2327 scriptlet_typelib_GetTypeInfoCount,
2328 scriptlet_typelib_GetTypeInfo,
2329 scriptlet_typelib_GetIDsOfNames,
2330 scriptlet_typelib_Invoke,
2331 scriptlet_typelib_AddURL,
2332 scriptlet_typelib_put_Path,
2333 scriptlet_typelib_get_Path,
2334 scriptlet_typelib_put_Doc,
2335 scriptlet_typelib_get_Doc,
2336 scriptlet_typelib_put_Name,
2337 scriptlet_typelib_get_Name,
2338 scriptlet_typelib_put_MajorVersion,
2339 scriptlet_typelib_get_MajorVersion,
2340 scriptlet_typelib_put_MinorVersion,
2341 scriptlet_typelib_get_MinorVersion,
2342 scriptlet_typelib_Write,
2343 scriptlet_typelib_Reset,
2344 scriptlet_typelib_put_GUID,
2345 scriptlet_typelib_get_GUID
2348 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
2350 TRACE("%p, %lu, %p\n", hinst, reason, reserved);
2352 switch (reason)
2354 case DLL_PROCESS_ATTACH:
2355 DisableThreadLibraryCalls(hinst);
2356 scrobj_instance = hinst;
2357 break;
2358 case DLL_PROCESS_DETACH:
2359 if (reserved) break;
2360 release_typelib();
2361 break;
2363 return TRUE;
2366 /***********************************************************************
2367 * DllInstall (scrobj.@)
2369 HRESULT WINAPI DllInstall(BOOL install, const WCHAR *arg)
2371 struct scriptlet_factory *factory;
2372 HRESULT hres;
2374 if (install)
2376 hres = DllRegisterServer();
2377 if (!arg || FAILED(hres)) return hres;
2379 else if (!arg)
2380 return DllUnregisterServer();
2382 hres = create_scriptlet_factory(arg, &factory);
2383 if (SUCCEEDED(hres))
2385 if (factory->have_registration)
2387 /* validate scripts */
2388 hres = create_scriptlet_hosts(factory, &factory->hosts);
2389 if (SUCCEEDED(hres)) hres = parse_scripts(factory, &factory->hosts, FALSE);
2391 else
2393 FIXME("No registration info\n");
2394 hres = E_FAIL;
2396 if (SUCCEEDED(hres))
2398 if (install)
2399 hres = register_scriptlet(factory);
2400 else
2401 hres = unregister_scriptlet(factory);
2403 IClassFactory_Release(&factory->IClassFactory_iface);
2406 return hres;
2409 static HRESULT WINAPI scriptlet_typelib_CreateInstance(IClassFactory *factory, IUnknown *outer, REFIID riid, void **obj)
2411 struct scriptlet_typelib *This;
2412 HRESULT hr;
2414 TRACE("(%p, %p, %s, %p)\n", factory, outer, debugstr_guid(riid), obj);
2416 *obj = NULL;
2418 if (!(This = calloc(1, sizeof(*This))))
2419 return E_OUTOFMEMORY;
2421 This->IGenScriptletTLib_iface.lpVtbl = &scriptlet_typelib_vtbl;
2422 This->ref = 1;
2424 hr = IGenScriptletTLib_QueryInterface(&This->IGenScriptletTLib_iface, riid, obj);
2425 IGenScriptletTLib_Release(&This->IGenScriptletTLib_iface);
2426 return hr;
2429 static HRESULT WINAPI scrruncf_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2431 *ppv = NULL;
2433 if (IsEqualGUID(&IID_IUnknown, riid))
2435 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
2436 *ppv = iface;
2438 else if (IsEqualGUID(&IID_IClassFactory, riid))
2440 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
2441 *ppv = iface;
2444 if (*ppv)
2446 IUnknown_AddRef((IUnknown *)*ppv);
2447 return S_OK;
2450 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
2451 return E_NOINTERFACE;
2454 static ULONG WINAPI scrruncf_AddRef(IClassFactory *iface)
2456 TRACE("(%p)\n", iface);
2457 return 2;
2460 static ULONG WINAPI scrruncf_Release(IClassFactory *iface)
2462 TRACE("(%p)\n", iface);
2463 return 1;
2466 static HRESULT WINAPI scrruncf_LockServer(IClassFactory *iface, BOOL fLock)
2468 TRACE("(%p)->(%x)\n", iface, fLock);
2469 return S_OK;
2472 static const struct IClassFactoryVtbl scriptlet_typelib_factory_vtbl =
2474 scrruncf_QueryInterface,
2475 scrruncf_AddRef,
2476 scrruncf_Release,
2477 scriptlet_typelib_CreateInstance,
2478 scrruncf_LockServer
2481 static IClassFactory scriptlet_typelib_factory = { &scriptlet_typelib_factory_vtbl };
2483 /***********************************************************************
2484 * DllGetClassObject (scrobj.@)
2486 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
2488 WCHAR key_name[128], *p;
2489 LONG size = 0;
2490 LSTATUS status;
2492 if (IsEqualGUID(&CLSID_TypeLib, rclsid))
2494 TRACE("(Scriptlet.TypeLib %s %p)\n", debugstr_guid(riid), ppv);
2495 return IClassFactory_QueryInterface(&scriptlet_typelib_factory, riid, ppv);
2498 wcscpy(key_name, L"CLSID\\");
2499 p = key_name + wcslen(key_name);
2500 p += StringFromGUID2(rclsid, p, ARRAY_SIZE(key_name) - (p - key_name)) - 1;
2501 wcscpy(p, L"\\ScriptletURL");
2502 status = RegQueryValueW(HKEY_CLASSES_ROOT, key_name, NULL, &size);
2503 if (!status)
2505 struct scriptlet_factory *factory;
2506 WCHAR *url;
2507 HRESULT hres;
2509 if (!(url = malloc(size * sizeof(WCHAR)))) return E_OUTOFMEMORY;
2510 status = RegQueryValueW(HKEY_CLASSES_ROOT, key_name, url, &size);
2512 hres = create_scriptlet_factory(url, &factory);
2513 free(url);
2514 if (FAILED(hres)) return hres;
2516 hres = IClassFactory_QueryInterface(&factory->IClassFactory_iface, riid, ppv);
2517 IClassFactory_Release(&factory->IClassFactory_iface);
2518 return hres;
2521 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
2522 return CLASS_E_CLASSNOTAVAILABLE;