[PATCH] msscript: Initial support for hosting script engines

Jacek Caban jacek at codeweavers.com
Fri Jul 15 06:32:14 CDT 2016


Hi Nikolay,

On 14.07.2016 16:35, Nikolay Sivov wrote:
> +static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret)
> +{
> +    IObjectSafety *objsafety;
> +    ScriptHost *host;
> +    HRESULT hr;
> +
> +    *ret = NULL;
> +
> +    host = heap_alloc(sizeof(*host));
> +    if (!host)
> +        return E_OUTOFMEMORY;
> +
> +    host->IActiveScriptSite_iface.lpVtbl = &ActiveScriptSiteVtbl;
> +    host->ref = 1;
> +    host->script = NULL;
> +    host->parse = NULL;
> +    host->clsid = *clsid;
> +
> +    hr = CoCreateInstance(&host->clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
> +            &IID_IActiveScript, (void**)&host->script);
> +    if (FAILED(hr)) {
> +        WARN("Failed to create an instance for %s, %#x\n", debugstr_guid(clsid), hr);
> +        goto failed;
> +    }
> +
> +    hr = IActiveScript_QueryInterface(host->script, &IID_IObjectSafety, (void**)&objsafety);
> +    if (FAILED(hr)) {
> +        FIXME("Could not get IObjectSafety, %#x\n", hr);
> +        goto failed;
> +    }
> +
> +    hr = IObjectSafety_SetInterfaceSafetyOptions(objsafety, &IID_IActiveScriptParse, INTERFACESAFE_FOR_UNTRUSTED_DATA, 0);
> +    if (FAILED(hr))
> +        FIXME("SetInterfaceSafetyOptions failed, %#x\n", hr);

This failure is important, please handle it well.

> +    IObjectSafety_Release(objsafety);
> +
> +    hr = IActiveScript_SetScriptSite(host->script, &host->IActiveScriptSite_iface);
> +    if (FAILED(hr)) {
> +        WARN("SetScriptSite failed, %#x\n", hr);
> +        goto failed;
> +    }
> +
> +    hr = IActiveScript_QueryInterface(host->script, &IID_IActiveScriptParse, (void**)&host->parse);
> +    if (FAILED(hr)) {
> +        WARN("Failed to get IActiveScriptParse, %#x\n", hr);
> +        goto failed;
> +    }

This and...

> +    hr = IActiveScriptParse_InitNew(host->parse);
> +    if (FAILED(hr)) {
> +        WARN("InitNew failed, %#x\n", hr);
> +        goto failed;
> +    }

...this failure will cause ref leak. You have already set script site,
so engine holds a reference to ScriptHost, but you only release one
reference on failure. Using release_script_engine on failure should fix
that.

> +
> +    *ret = host;
> +    return S_OK;
> +
> +failed:
> +    IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
> +    return hr;
> +}
> +
>  static HRESULT WINAPI ScriptControl_QueryInterface(IScriptControl *iface, REFIID riid, void **ppv)
>  {
>      ScriptControl *This = impl_from_IScriptControl(iface);
> @@ -257,6 +498,10 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface)
>      if(!ref) {
>          if (This->site)
>              IOleClientSite_Release(This->site);
> +        if (This->host) {
> +            release_script_engine(This->host);
> +            IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface);
> +        }
>          heap_free(This);
>      }
>  
> @@ -321,15 +566,47 @@ static HRESULT WINAPI ScriptControl_Invoke(IScriptControl *iface, DISPID dispIdM
>  static HRESULT WINAPI ScriptControl_get_Language(IScriptControl *iface, BSTR *p)
>  {
>      ScriptControl *This = impl_from_IScriptControl(iface);
> -    FIXME("(%p)->(%p)\n", This, p);
> -    return E_NOTIMPL;
> +    LPOLESTR progidW;
> +    HRESULT hr;
> +
> +    TRACE("(%p)->(%p)\n", This, p);
> +
> +    if (!p)
> +        return E_POINTER;
> +
> +    *p = NULL;
> +
> +    if (!This->host)
> +        return S_OK;
> +
> +    hr = ProgIDFromCLSID(&This->host->clsid, &progidW);
> +    if (FAILED(hr))
> +        return hr;
> +
> +    *p = SysAllocStringLen(progidW, lstrlenW(progidW));

How about SysAllocString instead?

> +    CoTaskMemFree(progidW);
> +    return *p ? S_OK : E_OUTOFMEMORY;
>  }
>  
>  static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR language)
>  {
>      ScriptControl *This = impl_from_IScriptControl(iface);
> -    FIXME("(%p)->(%s)\n", This, debugstr_w(language));
> -    return E_NOTIMPL;
> +    CLSID clsid;
> +
> +    TRACE("(%p)->(%s)\n", This, debugstr_w(language));
> +
> +    if (language && FAILED(CLSIDFromProgID(language, &clsid)))
> +        return CTL_E_INVALIDPROPERTYVALUE;
> +
> +    if (This->host) {
> +        IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface);
> +        This->host = NULL;
> +    }

This will leave zombie script host and engine. You should probably use
release_script_engine here as well.

> +
> +    if (!language)
> +        return S_OK;
> +
> +    return init_script_host(&clsid, &This->host);
>  }
>  
>  static HRESULT WINAPI ScriptControl_get_State(IScriptControl *iface, ScriptControlStates *p)
> @@ -1379,6 +1656,7 @@ static HRESULT WINAPI ScriptControl_CreateInstance(IClassFactory *iface, IUnknow
>      script_control->ref = 1;
>      script_control->site = NULL;
>      script_control->cp_list = NULL;
> +    script_control->host = NULL;
>  
>      ConnectionPoint_Init(&script_control->cp_scsource, script_control, &DIID_DScriptControlSource);
>      ConnectionPoint_Init(&script_control->cp_propnotif, script_control, &IID_IPropertyNotifySink);
>

Thanks,
Jacek
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20160715/6e12aacf/attachment.html>


More information about the wine-devel mailing list