| /* |
| * Copyright 2017 Nikolay Sivov |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| #define COBJMACROS |
| |
| #include "config.h" |
| #include <stdarg.h> |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "ole2.h" |
| #include "olectl.h" |
| #include "rpcproxy.h" |
| |
| #include "initguid.h" |
| #include "scrobj.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(scrobj); |
| |
| static HINSTANCE scrobj_instance; |
| |
| typedef enum tid_t |
| { |
| NULL_tid, |
| IGenScriptletTLib_tid, |
| LAST_tid |
| } tid_t; |
| |
| static ITypeLib *typelib; |
| static ITypeInfo *typeinfos[LAST_tid]; |
| |
| static REFIID tid_ids[] = { |
| &IID_NULL, |
| &IID_IGenScriptletTLib, |
| }; |
| |
| static HRESULT load_typelib(void) |
| { |
| HRESULT hres; |
| ITypeLib *tl; |
| |
| if (typelib) |
| return S_OK; |
| |
| hres = LoadRegTypeLib(&LIBID_Scriptlet, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl); |
| if (FAILED(hres)) |
| { |
| ERR("LoadRegTypeLib failed: %08x\n", hres); |
| return hres; |
| } |
| |
| if (InterlockedCompareExchangePointer((void **)&typelib, tl, NULL)) |
| ITypeLib_Release(tl); |
| return hres; |
| } |
| |
| static HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo) |
| { |
| HRESULT hres; |
| |
| if (FAILED(hres = load_typelib())) |
| return hres; |
| |
| if (!typeinfos[tid]) |
| { |
| ITypeInfo *ti; |
| |
| hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti); |
| if (FAILED(hres)) { |
| ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres); |
| return hres; |
| } |
| |
| if (InterlockedCompareExchangePointer((void **)(typeinfos+tid), ti, NULL)) |
| ITypeInfo_Release(ti); |
| } |
| |
| *typeinfo = typeinfos[tid]; |
| ITypeInfo_AddRef(typeinfos[tid]); |
| return S_OK; |
| } |
| |
| static void release_typelib(void) |
| { |
| unsigned i; |
| |
| if (!typelib) |
| return; |
| |
| for (i = 0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++) |
| if (typeinfos[i]) |
| ITypeInfo_Release(typeinfos[i]); |
| |
| ITypeLib_Release(typelib); |
| } |
| |
| struct scriptlet_typelib |
| { |
| IGenScriptletTLib IGenScriptletTLib_iface; |
| LONG ref; |
| |
| BSTR guid; |
| }; |
| |
| static inline struct scriptlet_typelib *impl_from_IGenScriptletTLib(IGenScriptletTLib *iface) |
| { |
| return CONTAINING_RECORD(iface, struct scriptlet_typelib, IGenScriptletTLib_iface); |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_QueryInterface(IGenScriptletTLib *iface, REFIID riid, void **obj) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), obj); |
| |
| if (IsEqualIID(riid, &IID_IGenScriptletTLib) || |
| IsEqualIID(riid, &IID_IDispatch) || |
| IsEqualIID(riid, &IID_IUnknown)) |
| { |
| *obj = iface; |
| IGenScriptletTLib_AddRef(iface); |
| return S_OK; |
| } |
| |
| *obj = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI scriptlet_typelib_AddRef(IGenScriptletTLib *iface) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| ULONG ref = InterlockedIncrement(&This->ref); |
| TRACE("(%p)->(%u)\n", This, ref); |
| return ref; |
| } |
| |
| static ULONG WINAPI scriptlet_typelib_Release(IGenScriptletTLib *iface) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| LONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p)->(%u)\n", This, ref); |
| |
| if (!ref) |
| { |
| SysFreeString(This->guid); |
| HeapFree(GetProcessHeap(), 0, This); |
| } |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_GetTypeInfoCount(IGenScriptletTLib *iface, UINT *count) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| TRACE("(%p, %p)\n", This, count); |
| |
| *count = 1; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_GetTypeInfo(IGenScriptletTLib *iface, UINT index, LCID lcid, |
| ITypeInfo **tinfo) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| TRACE("(%p, %u, %x, %p)\n", This, index, lcid, tinfo); |
| |
| return get_typeinfo(IGenScriptletTLib_tid, tinfo); |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_GetIDsOfNames(IGenScriptletTLib *iface, REFIID riid, LPOLESTR *names, |
| UINT cNames, LCID lcid, DISPID *dispid) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| ITypeInfo *typeinfo; |
| HRESULT hr; |
| |
| TRACE("(%p, %s, %p, %u, %x, %p)\n", This, debugstr_guid(riid), names, cNames, lcid, dispid); |
| |
| hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo); |
| if (SUCCEEDED(hr)) |
| { |
| hr = ITypeInfo_GetIDsOfNames(typeinfo, names, cNames, dispid); |
| ITypeInfo_Release(typeinfo); |
| } |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_Invoke(IGenScriptletTLib *iface, DISPID dispid, REFIID riid, |
| LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *ei, UINT *argerr) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| ITypeInfo *typeinfo; |
| HRESULT hr; |
| |
| TRACE("(%p, %d, %s, %x, %x, %p, %p, %p, %p)\n", This, dispid, debugstr_guid(riid), lcid, flags, |
| params, result, ei, argerr); |
| |
| hr = get_typeinfo(IGenScriptletTLib_tid, &typeinfo); |
| if (SUCCEEDED(hr)) |
| { |
| hr = ITypeInfo_Invoke(typeinfo, &This->IGenScriptletTLib_iface, dispid, flags, |
| params, result, ei, argerr); |
| ITypeInfo_Release(typeinfo); |
| } |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_AddURL(IGenScriptletTLib *iface, BSTR url) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %s): stub\n", This, debugstr_w(url)); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_put_Path(IGenScriptletTLib *iface, BSTR path) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %s): stub\n", This, debugstr_w(path)); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_get_Path(IGenScriptletTLib *iface, BSTR *path) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %p): stub\n", This, path); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_put_Doc(IGenScriptletTLib *iface, BSTR doc) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %s): stub\n", This, debugstr_w(doc)); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_get_Doc(IGenScriptletTLib *iface, BSTR *doc) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %p): stub\n", This, doc); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_put_Name(IGenScriptletTLib *iface, BSTR name) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %s): stub\n", This, debugstr_w(name)); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_get_Name(IGenScriptletTLib *iface, BSTR *name) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %p): stub\n", This, name); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_put_MajorVersion(IGenScriptletTLib *iface, WORD version) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %x): stub\n", This, version); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_get_MajorVersion(IGenScriptletTLib *iface, WORD *version) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %p): stub\n", This, version); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_put_MinorVersion(IGenScriptletTLib *iface, WORD version) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %x): stub\n", This, version); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_get_MinorVersion(IGenScriptletTLib *iface, WORD *version) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %p): stub\n", This, version); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_Write(IGenScriptletTLib *iface) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p): stub\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_Reset(IGenScriptletTLib *iface) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p): stub\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_put_GUID(IGenScriptletTLib *iface, BSTR guid) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| FIXME("(%p, %s): stub\n", This, debugstr_w(guid)); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_get_GUID(IGenScriptletTLib *iface, BSTR *ret) |
| { |
| struct scriptlet_typelib *This = impl_from_IGenScriptletTLib(iface); |
| |
| TRACE("(%p, %p)\n", This, ret); |
| |
| *ret = NULL; |
| |
| if (!This->guid) |
| { |
| WCHAR guidW[39]; |
| GUID guid; |
| HRESULT hr; |
| |
| hr = CoCreateGuid(&guid); |
| if (FAILED(hr)) |
| return hr; |
| |
| hr = StringFromGUID2(&guid, guidW, sizeof(guidW)/sizeof(guidW[0])); |
| if (FAILED(hr)) |
| return hr; |
| |
| if (!(This->guid = SysAllocString(guidW))) |
| return E_OUTOFMEMORY; |
| } |
| |
| *ret = SysAllocString(This->guid); |
| return *ret ? S_OK : E_OUTOFMEMORY; |
| } |
| |
| static const IGenScriptletTLibVtbl scriptlet_typelib_vtbl = |
| { |
| scriptlet_typelib_QueryInterface, |
| scriptlet_typelib_AddRef, |
| scriptlet_typelib_Release, |
| scriptlet_typelib_GetTypeInfoCount, |
| scriptlet_typelib_GetTypeInfo, |
| scriptlet_typelib_GetIDsOfNames, |
| scriptlet_typelib_Invoke, |
| scriptlet_typelib_AddURL, |
| scriptlet_typelib_put_Path, |
| scriptlet_typelib_get_Path, |
| scriptlet_typelib_put_Doc, |
| scriptlet_typelib_get_Doc, |
| scriptlet_typelib_put_Name, |
| scriptlet_typelib_get_Name, |
| scriptlet_typelib_put_MajorVersion, |
| scriptlet_typelib_get_MajorVersion, |
| scriptlet_typelib_put_MinorVersion, |
| scriptlet_typelib_get_MinorVersion, |
| scriptlet_typelib_Write, |
| scriptlet_typelib_Reset, |
| scriptlet_typelib_put_GUID, |
| scriptlet_typelib_get_GUID |
| }; |
| |
| BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) |
| { |
| TRACE("%p, %u, %p\n", hinst, reason, reserved); |
| |
| switch (reason) |
| { |
| case DLL_WINE_PREATTACH: |
| return FALSE; /* prefer native version */ |
| case DLL_PROCESS_ATTACH: |
| DisableThreadLibraryCalls(hinst); |
| scrobj_instance = hinst; |
| break; |
| case DLL_PROCESS_DETACH: |
| if (reserved) break; |
| release_typelib(); |
| break; |
| } |
| return TRUE; |
| } |
| |
| /*********************************************************************** |
| * DllRegisterServer (scrobj.@) |
| */ |
| HRESULT WINAPI DllRegisterServer(void) |
| { |
| TRACE("()\n"); |
| return __wine_register_resources(scrobj_instance); |
| } |
| |
| /*********************************************************************** |
| * DllUnregisterServer (scrobj.@) |
| */ |
| HRESULT WINAPI DllUnregisterServer(void) |
| { |
| TRACE("()\n"); |
| return __wine_unregister_resources(scrobj_instance); |
| } |
| |
| static HRESULT WINAPI scriptlet_typelib_CreateInstance(IClassFactory *factory, IUnknown *outer, REFIID riid, void **obj) |
| { |
| struct scriptlet_typelib *This; |
| HRESULT hr; |
| |
| TRACE("(%p, %p, %s, %p)\n", factory, outer, debugstr_guid(riid), obj); |
| |
| *obj = NULL; |
| |
| This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); |
| if (!This) |
| return E_OUTOFMEMORY; |
| |
| This->IGenScriptletTLib_iface.lpVtbl = &scriptlet_typelib_vtbl; |
| This->ref = 1; |
| This->guid = NULL; |
| |
| hr = IGenScriptletTLib_QueryInterface(&This->IGenScriptletTLib_iface, riid, obj); |
| IGenScriptletTLib_Release(&This->IGenScriptletTLib_iface); |
| return hr; |
| } |
| |
| static HRESULT WINAPI scrruncf_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) |
| { |
| *ppv = NULL; |
| |
| if (IsEqualGUID(&IID_IUnknown, riid)) |
| { |
| TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); |
| *ppv = iface; |
| } |
| else if (IsEqualGUID(&IID_IClassFactory, riid)) |
| { |
| TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); |
| *ppv = iface; |
| } |
| |
| if (*ppv) |
| { |
| IUnknown_AddRef((IUnknown *)*ppv); |
| return S_OK; |
| } |
| |
| WARN("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv); |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI scrruncf_AddRef(IClassFactory *iface) |
| { |
| TRACE("(%p)\n", iface); |
| return 2; |
| } |
| |
| static ULONG WINAPI scrruncf_Release(IClassFactory *iface) |
| { |
| TRACE("(%p)\n", iface); |
| return 1; |
| } |
| |
| static HRESULT WINAPI scrruncf_LockServer(IClassFactory *iface, BOOL fLock) |
| { |
| TRACE("(%p)->(%x)\n", iface, fLock); |
| return S_OK; |
| } |
| |
| static const struct IClassFactoryVtbl scriptlet_typelib_factory_vtbl = |
| { |
| scrruncf_QueryInterface, |
| scrruncf_AddRef, |
| scrruncf_Release, |
| scriptlet_typelib_CreateInstance, |
| scrruncf_LockServer |
| }; |
| |
| static IClassFactory scriptlet_typelib_factory = { &scriptlet_typelib_factory_vtbl }; |
| |
| /*********************************************************************** |
| * DllGetClassObject (scrobj.@) |
| */ |
| HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) |
| { |
| if (IsEqualGUID(&CLSID_TypeLib, rclsid)) |
| { |
| TRACE("(Scriptlet.TypeLib %s %p)\n", debugstr_guid(riid), ppv); |
| return IClassFactory_QueryInterface(&scriptlet_typelib_factory, riid, ppv); |
| } |
| |
| FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); |
| return CLASS_E_CLASSNOTAVAILABLE; |
| } |
| |
| /*********************************************************************** |
| * DllCanUnloadNow (scrobj.@) |
| */ |
| HRESULT WINAPI DllCanUnloadNow(void) |
| { |
| return S_FALSE; |
| } |