scrobj: Add GetDispID implementation.
[wine.git] / dlls / scrobj / scrobj.c
blobb0a8dc7d5593dd001e2ee82ce0f771d092a250b7
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 FIXME("(%p)->(%s %p)\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 FIXME("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, pdp, res, pei, caller);
1076 return DISP_E_MEMBERNOTFOUND;
1079 static HRESULT WINAPI scriptlet_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
1081 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1082 FIXME("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
1083 return E_NOTIMPL;
1086 static HRESULT WINAPI scriptlet_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
1088 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1089 FIXME("(%p)->(%x)\n", This, id);
1090 return E_NOTIMPL;
1093 static HRESULT WINAPI scriptlet_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
1095 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1096 FIXME("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex);
1097 return E_NOTIMPL;
1100 static HRESULT WINAPI scriptlet_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
1102 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1103 FIXME("(%p)->(%x %p)\n", This, id, pbstrName);
1104 return E_NOTIMPL;
1107 static HRESULT WINAPI scriptlet_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
1109 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1110 FIXME("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
1111 return E_NOTIMPL;
1114 static HRESULT WINAPI scriptlet_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
1116 struct scriptlet_instance *This = impl_from_IDispatchEx(iface);
1117 FIXME("(%p)->(%p)\n", This, ppunk);
1118 return E_NOTIMPL;
1121 static IDispatchExVtbl DispatchExVtbl = {
1122 scriptlet_QueryInterface,
1123 scriptlet_AddRef,
1124 scriptlet_Release,
1125 scriptlet_GetTypeInfoCount,
1126 scriptlet_GetTypeInfo,
1127 scriptlet_GetIDsOfNames,
1128 scriptlet_Invoke,
1129 scriptlet_GetDispID,
1130 scriptlet_InvokeEx,
1131 scriptlet_DeleteMemberByName,
1132 scriptlet_DeleteMemberByDispID,
1133 scriptlet_GetMemberProperties,
1134 scriptlet_GetMemberName,
1135 scriptlet_GetNextDispID,
1136 scriptlet_GetNameSpaceParent
1139 static HRESULT create_scriptlet_instance(struct scriptlet_factory *factory, IDispatchEx **disp)
1141 struct script_host *factory_host, *host;
1142 struct scriptlet_instance *obj;
1143 IDispatch *script_dispatch;
1144 HRESULT hres;
1146 if (!(obj = heap_alloc_zero(sizeof(*obj)))) return E_OUTOFMEMORY;
1148 obj->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
1149 obj->ref = 1;
1150 list_init(&obj->hosts);
1152 if (!(obj->global = heap_alloc(sizeof(*obj->global))))
1154 IDispatchEx_Release(&obj->IDispatchEx_iface);
1155 return E_OUTOFMEMORY;
1157 obj->global->IDispatchEx_iface.lpVtbl = &global_vtbl;
1158 obj->global->ref = 1;
1160 LIST_FOR_EACH_ENTRY(factory_host, &factory->hosts, struct script_host, entry)
1162 hres = create_script_host(factory_host->language, factory_host->active_script, &obj->hosts, &host);
1163 if (FAILED(hres)) break;
1164 host->object = obj;
1166 hres = IActiveScript_AddNamedItem(host->active_script, L"scriptlet",
1167 SCRIPTITEM_ISVISIBLE | SCRIPTITEM_GLOBALMEMBERS);
1168 if (FAILED(hres)) break;
1170 hres = IActiveScript_AddNamedItem(host->active_script, L"globals", SCRIPTITEM_ISVISIBLE);
1171 if (FAILED(hres)) break;
1173 hres = IActiveScript_GetScriptDispatch(host->active_script, NULL, &script_dispatch);
1174 if (FAILED(hres)) return hres;
1176 hres = IDispatch_QueryInterface(script_dispatch, &IID_IDispatchEx, (void**)&host->script_dispatch);
1177 IDispatch_Release(script_dispatch);
1178 if (FAILED(hres))
1180 FIXME("IDispatchEx not supported by script engine\n");
1181 return hres;
1185 if (SUCCEEDED(hres)) hres = parse_scripts(factory, &obj->hosts, TRUE);
1186 if (SUCCEEDED(hres)) hres = lookup_object_properties(obj, factory);
1187 if (FAILED(hres))
1189 IDispatchEx_Release(&obj->IDispatchEx_iface);
1190 return hres;
1193 *disp = &obj->IDispatchEx_iface;
1194 return S_OK;
1197 static const char *debugstr_xml_name(struct scriptlet_factory *factory)
1199 const WCHAR *str;
1200 UINT len;
1201 HRESULT hres;
1202 hres = IXmlReader_GetLocalName(factory->xml_reader, &str, &len);
1203 if (FAILED(hres)) return "#err";
1204 return debugstr_wn(str, len);
1207 static HRESULT next_xml_node(struct scriptlet_factory *factory, XmlNodeType *node_type)
1209 HRESULT hres;
1210 do hres = IXmlReader_Read(factory->xml_reader, node_type);
1211 while (hres == S_OK && *node_type == XmlNodeType_Whitespace);
1212 return hres;
1215 static BOOL is_xml_name(struct scriptlet_factory *factory, const WCHAR *name)
1217 const WCHAR *qname;
1218 UINT len;
1219 HRESULT hres;
1220 hres = IXmlReader_GetQualifiedName(factory->xml_reader, &qname, &len);
1221 return hres == S_OK && len == wcslen(name) && !memcmp(qname, name, len * sizeof(WCHAR));
1224 static HRESULT expect_end_element(struct scriptlet_factory *factory)
1226 XmlNodeType node_type;
1227 HRESULT hres;
1228 hres = next_xml_node(factory, &node_type);
1229 if (hres != S_OK || node_type != XmlNodeType_EndElement)
1231 FIXME("Unexpected node %u %s\n", node_type, debugstr_xml_name(factory));
1232 return E_FAIL;
1234 return S_OK;
1237 static HRESULT expect_no_attributes(struct scriptlet_factory *factory)
1239 UINT count;
1240 HRESULT hres;
1241 hres = IXmlReader_GetAttributeCount(factory->xml_reader, &count);
1242 if (FAILED(hres)) return hres;
1243 if (!count) return S_OK;
1244 FIXME("Unexpected attributes\n");
1245 return E_FAIL;
1248 static BOOL is_case_xml_name(struct scriptlet_factory *factory, const WCHAR *name)
1250 const WCHAR *qname;
1251 UINT len;
1252 HRESULT hres;
1253 hres = IXmlReader_GetQualifiedName(factory->xml_reader, &qname, &len);
1254 return hres == S_OK && len == wcslen(name) && !memicmp(qname, name, len * sizeof(WCHAR));
1257 static HRESULT read_xml_value(struct scriptlet_factory *factory, WCHAR **ret)
1259 const WCHAR *str;
1260 UINT len;
1261 HRESULT hres;
1262 hres = IXmlReader_GetValue(factory->xml_reader, &str, &len);
1263 if (FAILED(hres)) return hres;
1264 if (!(*ret = heap_alloc((len + 1) * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1265 memcpy(*ret, str, len * sizeof(WCHAR));
1266 (*ret)[len] = 0;
1267 return S_OK;
1270 static HRESULT parse_scriptlet_registration(struct scriptlet_factory *factory)
1272 HRESULT hres;
1274 if (factory->have_registration)
1276 FIXME("duplicated registration element\n");
1277 return E_FAIL;
1279 factory->have_registration = TRUE;
1281 for (;;)
1283 hres = IXmlReader_MoveToNextAttribute(factory->xml_reader);
1284 if (hres != S_OK) break;
1286 if (is_xml_name(factory, L"description"))
1288 if (factory->description)
1290 FIXME("Duplicated description\n");
1291 return E_FAIL;
1293 hres = read_xml_value(factory, &factory->description);
1294 if (FAILED(hres)) return hres;
1296 else if (is_case_xml_name(factory, L"progid"))
1298 if (factory->progid)
1300 FIXME("Duplicated progid\n");
1301 return E_FAIL;
1303 hres = read_xml_value(factory, &factory->progid);
1304 if (FAILED(hres)) return hres;
1306 else if (is_xml_name(factory, L"version"))
1308 if (factory->version)
1310 FIXME("Duplicated version\n");
1311 return E_FAIL;
1313 hres = read_xml_value(factory, &factory->version);
1314 if (FAILED(hres)) return hres;
1316 else if (is_xml_name(factory, L"classid"))
1318 if (factory->classid_str)
1320 FIXME("Duplicated classid attribute\n");
1321 return E_FAIL;
1323 hres = read_xml_value(factory, &factory->classid_str);
1324 if (FAILED(hres)) return hres;
1325 hres = IIDFromString(factory->classid_str, &factory->classid);
1326 if (FAILED(hres))
1328 FIXME("Invalid classid %s\n", debugstr_w(factory->classid_str));
1330 return E_FAIL;
1333 else
1335 FIXME("Unexpected attribute\n");
1336 return E_NOTIMPL;
1340 if (!factory->progid && !factory->classid_str)
1342 FIXME("Incomplet registration element\n");
1343 return E_FAIL;
1346 if (factory->progid)
1348 size_t progid_len = wcslen(factory->progid);
1349 size_t version_len = wcslen(factory->version);
1351 if (!(factory->versioned_progid = heap_alloc((progid_len + version_len + 2) * sizeof(WCHAR))))
1352 return E_OUTOFMEMORY;
1354 memcpy(factory->versioned_progid, factory->progid, (progid_len + 1) * sizeof(WCHAR));
1355 if (version_len)
1357 factory->versioned_progid[progid_len++] = '.';
1358 wcscpy(factory->versioned_progid + progid_len, factory->version);
1360 else factory->versioned_progid[progid_len] = 0;
1363 return expect_end_element(factory);
1366 static HRESULT parse_scriptlet_public(struct scriptlet_factory *factory)
1368 struct scriptlet_member *member, *member_iter;
1369 enum member_type member_type;
1370 XmlNodeType node_type;
1371 BOOL empty;
1372 HRESULT hres;
1374 TRACE("\n");
1376 if (factory->have_public)
1378 FIXME("duplicated public element\n");
1379 return E_FAIL;
1381 factory->have_public = TRUE;
1383 for (;;)
1385 hres = next_xml_node(factory, &node_type);
1386 if (FAILED(hres)) return hres;
1387 if (node_type == XmlNodeType_EndElement) break;
1388 if (node_type != XmlNodeType_Element)
1390 FIXME("Unexpected node type %u\n", node_type);
1391 return E_FAIL;
1394 if (is_xml_name(factory, L"method"))
1395 member_type = MEMBER_METHOD;
1396 else if (is_xml_name(factory, L"property"))
1397 member_type = MEMBER_PROPERTY;
1398 else
1400 FIXME("Unexpected element %s\n", debugstr_xml_name(factory));
1401 return E_NOTIMPL;
1404 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1406 hres = IXmlReader_MoveToAttributeByName(factory->xml_reader, L"name", NULL);
1407 if (hres != S_OK)
1409 FIXME("Missing method name\n");
1410 return E_FAIL;
1413 if (!(member = heap_alloc(sizeof(*member)))) return E_OUTOFMEMORY;
1414 member->type = member_type;
1416 hres = read_xml_value(factory, &member->name);
1417 if (FAILED(hres))
1419 heap_free(member);
1420 return hres;
1423 LIST_FOR_EACH_ENTRY(member_iter, &factory->members, struct scriptlet_member, entry)
1425 if (!wcsicmp(member_iter->name, member->name))
1427 FIXME("Duplicated member %s\n", debugstr_w(member->name));
1428 return E_FAIL;
1431 list_add_tail(&factory->members, &member->entry);
1433 switch (member_type)
1435 case MEMBER_METHOD:
1436 list_init(&member->u.parameters);
1438 if (empty) break;
1439 for (;;)
1441 struct method_parameter *parameter;
1443 hres = next_xml_node(factory, &node_type);
1444 if (FAILED(hres)) return hres;
1445 if (node_type == XmlNodeType_EndElement) break;
1446 if (node_type != XmlNodeType_Element)
1448 FIXME("Unexpected node type %u\n", node_type);
1449 return E_FAIL;
1451 if (!is_case_xml_name(factory, L"parameter"))
1453 FIXME("Unexpected method element\n");
1454 return E_FAIL;
1457 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1459 hres = IXmlReader_MoveToAttributeByName(factory->xml_reader, L"name", NULL);
1460 if (hres != S_OK)
1462 FIXME("Missing parameter name\n");
1463 return E_FAIL;
1466 if (!(parameter = heap_alloc(sizeof(*parameter)))) return E_OUTOFMEMORY;
1468 hres = read_xml_value(factory, &parameter->name);
1469 if (FAILED(hres)) return hres;
1470 list_add_tail(&member->u.parameters, &parameter->entry);
1471 if (!empty && FAILED(hres = expect_end_element(factory))) return hres;
1473 break;
1475 case MEMBER_PROPERTY:
1476 member->u.flags = 0;
1478 if (empty) break;
1479 for (;;)
1481 hres = next_xml_node(factory, &node_type);
1482 if (FAILED(hres)) return hres;
1483 if (node_type == XmlNodeType_EndElement) break;
1484 if (node_type != XmlNodeType_Element)
1486 FIXME("Unexpected node type %u\n", node_type);
1487 return E_FAIL;
1489 if (is_case_xml_name(factory, L"get"))
1491 if (member->u.flags & PROP_GETTER)
1493 FIXME("Duplicated getter\n");
1494 return E_FAIL;
1496 member->u.flags |= PROP_GETTER;
1498 else if (is_case_xml_name(factory, L"put"))
1500 if (member->u.flags & PROP_SETTER)
1502 FIXME("Duplicated setter\n");
1503 return E_FAIL;
1505 member->u.flags |= PROP_SETTER;
1507 else
1509 FIXME("Unexpected property element %s\n", debugstr_xml_name(factory));
1510 return E_FAIL;
1513 empty = IXmlReader_IsEmptyElement(factory->xml_reader);
1514 if (!empty && FAILED(hres = expect_end_element(factory))) return hres;
1516 if (!member->u.flags)
1518 FIXME("No getter or setter\n");
1519 return E_NOTIMPL;
1521 break;
1523 if (FAILED(hres)) return hres;
1526 return S_OK;
1529 static HRESULT parse_scriptlet_script(struct scriptlet_factory *factory, struct scriptlet_script *script)
1531 XmlNodeType node_type;
1532 HRESULT hres;
1534 for (;;)
1536 hres = IXmlReader_MoveToNextAttribute(factory->xml_reader);
1537 if (hres != S_OK) break;
1539 if (is_xml_name(factory, L"language"))
1541 if (script->language)
1543 FIXME("Duplicated language\n");
1544 return E_FAIL;
1546 hres = read_xml_value(factory, &script->language);
1547 if (FAILED(hres)) return hres;
1549 else
1551 FIXME("Unexpected attribute\n");
1552 return E_NOTIMPL;
1556 if (!script->language)
1558 FIXME("Language not specified\n");
1559 return E_FAIL;
1562 if (FAILED(hres = next_xml_node(factory, &node_type))) return hres;
1564 if (node_type != XmlNodeType_Text && node_type != XmlNodeType_CDATA)
1566 FIXME("Unexpected node type %u\n", node_type);
1567 return E_FAIL;
1570 hres = read_xml_value(factory, &script->body);
1571 if (FAILED(hres)) return hres;
1573 return expect_end_element(factory);
1576 static HRESULT parse_scriptlet_file(struct scriptlet_factory *factory, const WCHAR *url)
1578 XmlNodeType node_type;
1579 IBindCtx *bind_ctx;
1580 IStream *stream;
1581 HRESULT hres;
1583 hres = CreateURLMoniker(NULL, url, &factory->moniker);
1584 if (FAILED(hres))
1586 WARN("CreateURLMoniker failed: %08x\n", hres);
1587 return hres;
1590 hres = CreateBindCtx(0, &bind_ctx);
1591 if(FAILED(hres))
1592 return hres;
1594 hres = IMoniker_BindToStorage(factory->moniker, bind_ctx, NULL, &IID_IStream, (void**)&stream);
1595 IBindCtx_Release(bind_ctx);
1596 if (FAILED(hres))
1597 return hres;
1599 hres = CreateXmlReader(&IID_IXmlReader, (void**)&factory->xml_reader, NULL);
1600 if(SUCCEEDED(hres))
1601 hres = IXmlReader_SetInput(factory->xml_reader, (IUnknown*)stream);
1602 IStream_Release(stream);
1603 if (FAILED(hres))
1604 return hres;
1606 hres = next_xml_node(factory, &node_type);
1607 if (hres == S_OK && node_type == XmlNodeType_XmlDeclaration)
1608 hres = next_xml_node(factory, &node_type);
1610 if (node_type != XmlNodeType_Element || !is_xml_name(factory, L"component"))
1612 FIXME("Unexpected %s element\n", debugstr_xml_name(factory));
1613 return E_FAIL;
1616 hres = expect_no_attributes(factory);
1617 if (FAILED(hres)) return hres;
1619 for (;;)
1621 hres = next_xml_node(factory, &node_type);
1622 if (FAILED(hres)) return hres;
1623 if (node_type == XmlNodeType_EndElement) break;
1624 if (node_type != XmlNodeType_Element)
1626 FIXME("Unexpected node type %u\n", node_type);
1627 return E_FAIL;
1630 if (is_xml_name(factory, L"registration"))
1631 hres = parse_scriptlet_registration(factory);
1632 else if (is_xml_name(factory, L"public"))
1633 hres = parse_scriptlet_public(factory);
1634 else if (is_xml_name(factory, L"script"))
1636 struct scriptlet_script *script;
1637 if (!(script = heap_alloc_zero(sizeof(*script)))) return E_OUTOFMEMORY;
1638 list_add_tail(&factory->scripts, &script->entry);
1639 hres = parse_scriptlet_script(factory, script);
1640 if (FAILED(hres)) return hres;
1642 else
1644 FIXME("Unexpected element %s\n", debugstr_xml_name(factory));
1645 return E_NOTIMPL;
1647 if (FAILED(hres)) return hres;
1650 hres = next_xml_node(factory, &node_type);
1651 if (hres != S_FALSE)
1653 FIXME("Unexpected node type %u\n", node_type);
1654 return E_FAIL;
1656 return S_OK;
1659 static inline struct scriptlet_factory *impl_from_IClassFactory(IClassFactory *iface)
1661 return CONTAINING_RECORD(iface, struct scriptlet_factory, IClassFactory_iface);
1664 static HRESULT WINAPI scriptlet_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
1666 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1668 if (IsEqualGUID(&IID_IUnknown, riid))
1670 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
1671 *ppv = &This->IClassFactory_iface;
1673 else if (IsEqualGUID(&IID_IClassFactory, riid))
1675 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
1676 *ppv = &This->IClassFactory_iface;
1678 else
1680 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
1681 *ppv = NULL;
1682 return E_NOINTERFACE;
1685 IUnknown_AddRef((IUnknown *)*ppv);
1686 return S_OK;
1689 static ULONG WINAPI scriptlet_factory_AddRef(IClassFactory *iface)
1691 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1692 ULONG ref = InterlockedIncrement(&This->ref);
1694 TRACE("(%p) ref=%d\n", This, ref);
1696 return ref;
1699 static ULONG WINAPI scriptlet_factory_Release(IClassFactory *iface)
1701 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1702 ULONG ref = InterlockedDecrement(&This->ref);
1704 TRACE("(%p) ref=%d\n", This, ref);
1706 if (!ref)
1708 if (This->moniker) IMoniker_Release(This->moniker);
1709 if (This->xml_reader) IXmlReader_Release(This->xml_reader);
1710 detach_script_hosts(&This->hosts);
1711 while (!list_empty(&This->members))
1713 struct scriptlet_member *member = LIST_ENTRY(list_head(&This->members), struct scriptlet_member, entry);
1714 list_remove(&member->entry);
1715 heap_free(member->name);
1716 if (member->type == MEMBER_METHOD)
1718 while (!list_empty(&member->u.parameters))
1720 struct method_parameter *parameter = LIST_ENTRY(list_head(&member->u.parameters), struct method_parameter, entry);
1721 list_remove(&parameter->entry);
1722 heap_free(parameter->name);
1723 heap_free(parameter);
1726 heap_free(member);
1728 while (!list_empty(&This->scripts))
1730 struct scriptlet_script *script = LIST_ENTRY(list_head(&This->scripts), struct scriptlet_script, entry);
1731 list_remove(&script->entry);
1732 heap_free(script->language);
1733 heap_free(script->body);
1734 heap_free(script);
1736 heap_free(This->classid_str);
1737 heap_free(This->description);
1738 heap_free(This->versioned_progid);
1739 heap_free(This->progid);
1740 heap_free(This->version);
1741 heap_free(This);
1743 return ref;
1746 static HRESULT WINAPI scriptlet_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1748 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1749 IDispatchEx *disp;
1750 HRESULT hres;
1752 TRACE("(%p)->(%p %s %p)\n", This, outer, debugstr_guid(riid), ppv);
1754 if (outer) FIXME("outer not supported\n");
1756 if (list_empty(&This->hosts))
1758 hres = create_scriptlet_hosts(This, &This->hosts);
1759 if (FAILED(hres)) return hres;
1761 hres = parse_scripts(This, &This->hosts, FALSE);
1762 if (FAILED(hres))
1764 detach_script_hosts(&This->hosts);
1765 return hres;
1769 hres = create_scriptlet_instance(This, &disp);
1770 if (FAILED(hres)) return hres;
1772 hres = IDispatchEx_QueryInterface(disp, riid, ppv);
1773 IDispatchEx_Release(disp);
1774 return hres;
1777 static HRESULT WINAPI scriptlet_factory_LockServer(IClassFactory *iface, BOOL fLock)
1779 struct scriptlet_factory *This = impl_from_IClassFactory(iface);
1780 TRACE("(%p)->(%x)\n", This, fLock);
1781 return S_OK;
1784 static const struct IClassFactoryVtbl scriptlet_factory_vtbl =
1786 scriptlet_factory_QueryInterface,
1787 scriptlet_factory_AddRef,
1788 scriptlet_factory_Release,
1789 scriptlet_factory_CreateInstance,
1790 scriptlet_factory_LockServer
1793 static HRESULT create_scriptlet_factory(const WCHAR *url, struct scriptlet_factory **ret)
1795 struct scriptlet_factory *factory;
1796 HRESULT hres;
1798 TRACE("%s\n", debugstr_w(url));
1800 if (!(factory = heap_alloc_zero(sizeof(*factory))))
1802 IClassFactory_Release(&factory->IClassFactory_iface);
1803 return E_OUTOFMEMORY;
1806 factory->IClassFactory_iface.lpVtbl = &scriptlet_factory_vtbl;
1807 factory->ref = 1;
1808 list_init(&factory->hosts);
1809 list_init(&factory->members);
1810 list_init(&factory->scripts);
1812 hres = parse_scriptlet_file(factory, url);
1813 if (FAILED(hres))
1815 IClassFactory_Release(&factory->IClassFactory_iface);
1816 return hres;
1819 *ret = factory;
1820 return S_OK;
1823 static HRESULT register_scriptlet(struct scriptlet_factory *factory)
1825 HKEY key, clsid_key, obj_key;
1826 LSTATUS status;
1827 HRESULT hres;
1829 if (factory->classid_str)
1831 WCHAR *url;
1833 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"CLSID", &clsid_key);
1834 if (status) return E_ACCESSDENIED;
1836 status = RegCreateKeyW(clsid_key, factory->classid_str, &obj_key);
1837 RegCloseKey(clsid_key);
1838 if (status) return E_ACCESSDENIED;
1840 hres = IMoniker_GetDisplayName(factory->moniker, NULL, NULL, &url);
1841 if (FAILED(hres))
1843 RegCloseKey(obj_key);
1844 return hres;
1846 status = RegCreateKeyW(obj_key, L"ScriptletURL", &key);
1847 if (!status)
1849 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)url,
1850 (wcslen(url) + 1) * sizeof(WCHAR));
1851 RegCloseKey(key);
1853 CoTaskMemFree(url);
1855 if (factory->description)
1856 status = RegSetValueExW(obj_key, NULL, 0, REG_SZ, (BYTE*)factory->description,
1857 (wcslen(factory->description) + 1) * sizeof(WCHAR));
1859 if (!status)
1861 status = RegCreateKeyW(obj_key, L"InprocServer32", &key);
1862 if (!status)
1864 WCHAR str[MAX_PATH];
1865 GetModuleFileNameW(scrobj_instance, str, MAX_PATH);
1866 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)str, (wcslen(str) + 1) * sizeof(WCHAR));
1867 RegCloseKey(key);
1871 if (!status && factory->versioned_progid)
1873 status = RegCreateKeyW(obj_key, L"ProgID", &key);
1874 if (!status)
1876 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->versioned_progid,
1877 (wcslen(factory->versioned_progid) + 1) * sizeof(WCHAR));
1878 RegCloseKey(key);
1882 if (!status && factory->progid)
1884 status = RegCreateKeyW(obj_key, L"VersionIndependentProgID", &key);
1885 if (!status)
1887 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->progid,
1888 (wcslen(factory->progid) + 1) * sizeof(WCHAR));
1889 RegCloseKey(key);
1893 RegCloseKey(obj_key);
1894 if (status) return E_ACCESSDENIED;
1897 if (factory->progid)
1899 status = RegCreateKeyW(HKEY_CLASSES_ROOT, factory->progid, &key);
1900 if (status) return E_ACCESSDENIED;
1902 if (factory->description)
1903 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->description,
1904 (wcslen(factory->description) + 1) * sizeof(WCHAR));
1906 if (!status && factory->classid_str)
1908 status = RegCreateKeyW(key, L"CLSID", &clsid_key);
1909 if (!status)
1911 status = RegSetValueExW(clsid_key, NULL, 0, REG_SZ, (BYTE*)factory->classid_str,
1912 (wcslen(factory->classid_str) + 1) * sizeof(WCHAR));
1913 RegCloseKey(clsid_key);
1917 RegCloseKey(key);
1918 if (status) return E_ACCESSDENIED;
1921 if (factory->versioned_progid)
1923 status = RegCreateKeyW(HKEY_CLASSES_ROOT, factory->versioned_progid, &key);
1924 if (status) return E_ACCESSDENIED;
1926 if (factory->description)
1927 status = RegSetValueExW(key, NULL, 0, REG_SZ, (BYTE*)factory->description,
1928 (wcslen(factory->description) + 1) * sizeof(WCHAR));
1930 if (!status && factory->classid_str)
1932 status = RegCreateKeyW(key, L"CLSID", &clsid_key);
1933 if (!status)
1935 status = RegSetValueExW(clsid_key, NULL, 0, REG_SZ, (BYTE*)factory->classid_str,
1936 (wcslen(factory->classid_str) + 1) * sizeof(WCHAR));
1937 RegCloseKey(clsid_key);
1941 RegCloseKey(key);
1942 if (status) return E_ACCESSDENIED;
1945 return S_OK;
1948 static HRESULT unregister_scriptlet(struct scriptlet_factory *factory)
1950 LSTATUS status;
1952 if (factory->classid_str)
1954 HKEY clsid_key;
1955 status = RegCreateKeyW(HKEY_CLASSES_ROOT, L"CLSID", &clsid_key);
1956 if (!status)
1958 RegDeleteTreeW(clsid_key, factory->classid_str);
1959 RegCloseKey(clsid_key);
1963 if (factory->progid) RegDeleteTreeW(HKEY_CLASSES_ROOT, factory->progid);
1964 if (factory->versioned_progid) RegDeleteTreeW(HKEY_CLASSES_ROOT, factory->versioned_progid);
1965 return S_OK;
1968 struct scriptlet_typelib
1970 IGenScriptletTLib IGenScriptletTLib_iface;
1971 LONG ref;
1973 BSTR guid;
1976 static inline struct scriptlet_typelib *impl_from_IGenScriptletTLib(IGenScriptletTLib *iface)
1978 return CONTAINING_RECORD(iface, struct scriptlet_typelib, IGenScriptletTLib_iface);
1981 static HRESULT WINAPI scriptlet_typelib_QueryInterface(IGenScriptletTLib *iface, REFIID riid, void **obj)
1983 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
1985 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), obj);
1987 if (IsEqualIID(riid, &IID_IGenScriptletTLib) ||
1988 IsEqualIID(riid, &IID_IDispatch) ||
1989 IsEqualIID(riid, &IID_IUnknown))
1991 *obj = iface;
1992 IGenScriptletTLib_AddRef(iface);
1993 return S_OK;
1996 *obj = NULL;
1997 return E_NOINTERFACE;
2000 static ULONG WINAPI scriptlet_typelib_AddRef(IGenScriptletTLib *iface)
2002 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2003 ULONG ref = InterlockedIncrement(&This->ref);
2004 TRACE("(%p)->(%u)\n", This, ref);
2005 return ref;
2008 static ULONG WINAPI scriptlet_typelib_Release(IGenScriptletTLib *iface)
2010 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2011 LONG ref = InterlockedDecrement(&This->ref);
2013 TRACE("(%p)->(%u)\n", This, ref);
2015 if (!ref)
2017 SysFreeString(This->guid);
2018 HeapFree(GetProcessHeap(), 0, This);
2021 return ref;
2024 static HRESULT WINAPI scriptlet_typelib_GetTypeInfoCount(IGenScriptletTLib *iface, UINT *count)
2026 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2028 TRACE("(%p, %p)\n", This, count);
2030 *count = 1;
2031 return S_OK;
2034 static HRESULT WINAPI scriptlet_typelib_GetTypeInfo(IGenScriptletTLib *iface, UINT index, LCID lcid,
2035 ITypeInfo **tinfo)
2037 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2039 TRACE("(%p, %u, %x, %p)\n", This, index, lcid, tinfo);
2041 return get_typeinfo(IGenScriptletTLib_tid, tinfo);
2044 static HRESULT WINAPI scriptlet_typelib_GetIDsOfNames(IGenScriptletTLib *iface, REFIID riid, LPOLESTR *names,
2045 UINT cNames, LCID lcid, DISPID *dispid)
2047 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2048 ITypeInfo *typeinfo;
2049 HRESULT hr;
2051 TRACE("(%p, %s, %p, %u, %x, %p)\n", This, debugstr_guid(riid), names, cNames, lcid, dispid);
2053 hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo);
2054 if (SUCCEEDED(hr))
2056 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, cNames, dispid);
2057 ITypeInfo_Release(typeinfo);
2060 return hr;
2063 static HRESULT WINAPI scriptlet_typelib_Invoke(IGenScriptletTLib *iface, DISPID dispid, REFIID riid,
2064 LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *ei, UINT *argerr)
2066 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2067 ITypeInfo *typeinfo;
2068 HRESULT hr;
2070 TRACE("(%p, %d, %s, %x, %x, %p, %p, %p, %p)\n", This, dispid, debugstr_guid(riid), lcid, flags,
2071 params, result, ei, argerr);
2073 hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo);
2074 if (SUCCEEDED(hr))
2076 hr = ITypeInfo_Invoke(typeinfo, &This->IGenScriptletTLib_iface, dispid, flags,
2077 params, result, ei, argerr);
2078 ITypeInfo_Release(typeinfo);
2081 return hr;
2084 static HRESULT WINAPI scriptlet_typelib_AddURL(IGenScriptletTLib *iface, BSTR url)
2086 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2088 FIXME("(%p, %s): stub\n", This, debugstr_w(url));
2090 return E_NOTIMPL;
2093 static HRESULT WINAPI scriptlet_typelib_put_Path(IGenScriptletTLib *iface, BSTR path)
2095 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2097 FIXME("(%p, %s): stub\n", This, debugstr_w(path));
2099 return E_NOTIMPL;
2102 static HRESULT WINAPI scriptlet_typelib_get_Path(IGenScriptletTLib *iface, BSTR *path)
2104 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2106 FIXME("(%p, %p): stub\n", This, path);
2108 return E_NOTIMPL;
2111 static HRESULT WINAPI scriptlet_typelib_put_Doc(IGenScriptletTLib *iface, BSTR doc)
2113 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2115 FIXME("(%p, %s): stub\n", This, debugstr_w(doc));
2117 return E_NOTIMPL;
2120 static HRESULT WINAPI scriptlet_typelib_get_Doc(IGenScriptletTLib *iface, BSTR *doc)
2122 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2124 FIXME("(%p, %p): stub\n", This, doc);
2126 return E_NOTIMPL;
2129 static HRESULT WINAPI scriptlet_typelib_put_Name(IGenScriptletTLib *iface, BSTR name)
2131 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2133 FIXME("(%p, %s): stub\n", This, debugstr_w(name));
2135 return E_NOTIMPL;
2138 static HRESULT WINAPI scriptlet_typelib_get_Name(IGenScriptletTLib *iface, BSTR *name)
2140 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2142 FIXME("(%p, %p): stub\n", This, name);
2144 return E_NOTIMPL;
2147 static HRESULT WINAPI scriptlet_typelib_put_MajorVersion(IGenScriptletTLib *iface, WORD version)
2149 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2151 FIXME("(%p, %x): stub\n", This, version);
2153 return E_NOTIMPL;
2156 static HRESULT WINAPI scriptlet_typelib_get_MajorVersion(IGenScriptletTLib *iface, WORD *version)
2158 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2160 FIXME("(%p, %p): stub\n", This, version);
2162 return E_NOTIMPL;
2165 static HRESULT WINAPI scriptlet_typelib_put_MinorVersion(IGenScriptletTLib *iface, WORD version)
2167 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2169 FIXME("(%p, %x): stub\n", This, version);
2171 return E_NOTIMPL;
2174 static HRESULT WINAPI scriptlet_typelib_get_MinorVersion(IGenScriptletTLib *iface, WORD *version)
2176 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2178 FIXME("(%p, %p): stub\n", This, version);
2180 return E_NOTIMPL;
2183 static HRESULT WINAPI scriptlet_typelib_Write(IGenScriptletTLib *iface)
2185 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2187 FIXME("(%p): stub\n", This);
2189 return E_NOTIMPL;
2192 static HRESULT WINAPI scriptlet_typelib_Reset(IGenScriptletTLib *iface)
2194 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2196 FIXME("(%p): stub\n", This);
2198 return E_NOTIMPL;
2201 static HRESULT WINAPI scriptlet_typelib_put_GUID(IGenScriptletTLib *iface, BSTR guid)
2203 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2205 FIXME("(%p, %s): stub\n", This, debugstr_w(guid));
2207 return E_NOTIMPL;
2210 static HRESULT WINAPI scriptlet_typelib_get_GUID(IGenScriptletTLib *iface, BSTR *ret)
2212 struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface);
2214 TRACE("(%p, %p)\n", This, ret);
2216 *ret = NULL;
2218 if (!This->guid)
2220 WCHAR guidW[39];
2221 GUID guid;
2222 HRESULT hr;
2224 hr = CoCreateGuid(&guid);
2225 if (FAILED(hr))
2226 return hr;
2228 hr = StringFromGUID2(&guid, guidW, ARRAY_SIZE(guidW));
2229 if (FAILED(hr))
2230 return hr;
2232 if (!(This->guid = SysAllocString(guidW)))
2233 return E_OUTOFMEMORY;
2236 *ret = SysAllocString(This->guid);
2237 return *ret ? S_OK : E_OUTOFMEMORY;
2240 static const IGenScriptletTLibVtbl scriptlet_typelib_vtbl =
2242 scriptlet_typelib_QueryInterface,
2243 scriptlet_typelib_AddRef,
2244 scriptlet_typelib_Release,
2245 scriptlet_typelib_GetTypeInfoCount,
2246 scriptlet_typelib_GetTypeInfo,
2247 scriptlet_typelib_GetIDsOfNames,
2248 scriptlet_typelib_Invoke,
2249 scriptlet_typelib_AddURL,
2250 scriptlet_typelib_put_Path,
2251 scriptlet_typelib_get_Path,
2252 scriptlet_typelib_put_Doc,
2253 scriptlet_typelib_get_Doc,
2254 scriptlet_typelib_put_Name,
2255 scriptlet_typelib_get_Name,
2256 scriptlet_typelib_put_MajorVersion,
2257 scriptlet_typelib_get_MajorVersion,
2258 scriptlet_typelib_put_MinorVersion,
2259 scriptlet_typelib_get_MinorVersion,
2260 scriptlet_typelib_Write,
2261 scriptlet_typelib_Reset,
2262 scriptlet_typelib_put_GUID,
2263 scriptlet_typelib_get_GUID
2266 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
2268 TRACE("%p, %u, %p\n", hinst, reason, reserved);
2270 switch (reason)
2272 case DLL_WINE_PREATTACH:
2273 return FALSE; /* prefer native version */
2274 case DLL_PROCESS_ATTACH:
2275 DisableThreadLibraryCalls(hinst);
2276 scrobj_instance = hinst;
2277 break;
2278 case DLL_PROCESS_DETACH:
2279 if (reserved) break;
2280 release_typelib();
2281 break;
2283 return TRUE;
2286 /***********************************************************************
2287 * DllRegisterServer (scrobj.@)
2289 HRESULT WINAPI DllRegisterServer(void)
2291 TRACE("()\n");
2292 return __wine_register_resources(scrobj_instance);
2295 /***********************************************************************
2296 * DllUnregisterServer (scrobj.@)
2298 HRESULT WINAPI DllUnregisterServer(void)
2300 TRACE("()\n");
2301 return __wine_unregister_resources(scrobj_instance);
2304 /***********************************************************************
2305 * DllInstall (scrobj.@)
2307 HRESULT WINAPI DllInstall(BOOL install, const WCHAR *arg)
2309 struct scriptlet_factory *factory;
2310 HRESULT hres;
2312 if (install)
2314 hres = DllRegisterServer();
2315 if (!arg || FAILED(hres)) return hres;
2317 else if (!arg)
2318 return DllUnregisterServer();
2320 hres = create_scriptlet_factory(arg, &factory);
2321 if (SUCCEEDED(hres))
2323 if (factory->have_registration)
2325 /* validate scripts */
2326 hres = create_scriptlet_hosts(factory, &factory->hosts);
2327 if (SUCCEEDED(hres)) hres = parse_scripts(factory, &factory->hosts, FALSE);
2329 else
2331 FIXME("No registration info\n");
2332 hres = E_FAIL;
2334 if (SUCCEEDED(hres))
2336 if (install)
2337 hres = register_scriptlet(factory);
2338 else
2339 hres = unregister_scriptlet(factory);
2341 IClassFactory_Release(&factory->IClassFactory_iface);
2344 return hres;
2347 static HRESULT WINAPI scriptlet_typelib_CreateInstance(IClassFactory *factory, IUnknown *outer, REFIID riid, void **obj)
2349 struct scriptlet_typelib *This;
2350 HRESULT hr;
2352 TRACE("(%p, %p, %s, %p)\n", factory, outer, debugstr_guid(riid), obj);
2354 *obj = NULL;
2356 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2357 if (!This)
2358 return E_OUTOFMEMORY;
2360 This->IGenScriptletTLib_iface.lpVtbl = &scriptlet_typelib_vtbl;
2361 This->ref = 1;
2362 This->guid = NULL;
2364 hr = IGenScriptletTLib_QueryInterface(&This->IGenScriptletTLib_iface, riid, obj);
2365 IGenScriptletTLib_Release(&This->IGenScriptletTLib_iface);
2366 return hr;
2369 static HRESULT WINAPI scrruncf_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2371 *ppv = NULL;
2373 if (IsEqualGUID(&IID_IUnknown, riid))
2375 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
2376 *ppv = iface;
2378 else if (IsEqualGUID(&IID_IClassFactory, riid))
2380 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
2381 *ppv = iface;
2384 if (*ppv)
2386 IUnknown_AddRef((IUnknown *)*ppv);
2387 return S_OK;
2390 WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
2391 return E_NOINTERFACE;
2394 static ULONG WINAPI scrruncf_AddRef(IClassFactory *iface)
2396 TRACE("(%p)\n", iface);
2397 return 2;
2400 static ULONG WINAPI scrruncf_Release(IClassFactory *iface)
2402 TRACE("(%p)\n", iface);
2403 return 1;
2406 static HRESULT WINAPI scrruncf_LockServer(IClassFactory *iface, BOOL fLock)
2408 TRACE("(%p)->(%x)\n", iface, fLock);
2409 return S_OK;
2412 static const struct IClassFactoryVtbl scriptlet_typelib_factory_vtbl =
2414 scrruncf_QueryInterface,
2415 scrruncf_AddRef,
2416 scrruncf_Release,
2417 scriptlet_typelib_CreateInstance,
2418 scrruncf_LockServer
2421 static IClassFactory scriptlet_typelib_factory = { &scriptlet_typelib_factory_vtbl };
2423 /***********************************************************************
2424 * DllGetClassObject (scrobj.@)
2426 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
2428 WCHAR key_name[128], *p;
2429 LONG size = 0;
2430 LSTATUS status;
2432 if (IsEqualGUID(&CLSID_TypeLib, rclsid))
2434 TRACE("(Scriptlet.TypeLib %s %p)\n", debugstr_guid(riid), ppv);
2435 return IClassFactory_QueryInterface(&scriptlet_typelib_factory, riid, ppv);
2438 wcscpy(key_name, L"CLSID\\");
2439 p = key_name + wcslen(key_name);
2440 p += StringFromGUID2(rclsid, p, ARRAY_SIZE(key_name) - (p - key_name)) - 1;
2441 wcscpy(p, L"\\ScriptletURL");
2442 status = RegQueryValueW(HKEY_CLASSES_ROOT, key_name, NULL, &size);
2443 if (!status)
2445 struct scriptlet_factory *factory;
2446 WCHAR *url;
2447 HRESULT hres;
2449 if (!(url = heap_alloc(size * sizeof(WCHAR)))) return E_OUTOFMEMORY;
2450 status = RegQueryValueW(HKEY_CLASSES_ROOT, key_name, url, &size);
2452 hres = create_scriptlet_factory(url, &factory);
2453 heap_free(url);
2454 if (FAILED(hres)) return hres;
2456 hres = IClassFactory_QueryInterface(&factory->IClassFactory_iface, riid, ppv);
2457 IClassFactory_Release(&factory->IClassFactory_iface);
2458 return hres;
2461 FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
2462 return CLASS_E_CLASSNOTAVAILABLE;
2465 /***********************************************************************
2466 * DllCanUnloadNow (scrobj.@)
2468 HRESULT WINAPI DllCanUnloadNow(void)
2470 return S_FALSE;