[PATCH v5 02/10] msscript.ocx: Release the script engine only when the last module is detached.

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Jun 19 07:53:31 CDT 2020


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/msscript.ocx/msscript.c | 88 +++++++++++++++++++++---------------
 1 file changed, 51 insertions(+), 37 deletions(-)

diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c
index 7385ce1..3d65067 100644
--- a/dlls/msscript.ocx/msscript.c
+++ b/dlls/msscript.ocx/msscript.c
@@ -51,6 +51,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msscript);
 
 struct ScriptControl;
 typedef struct ConnectionPoint ConnectionPoint;
+typedef struct ScriptHost ScriptHost;
 
 struct ConnectionPoint {
     IConnectionPoint IConnectionPoint_iface;
@@ -68,9 +69,11 @@ struct named_item {
 typedef struct {
     IScriptModule IScriptModule_iface;
     LONG ref;
+
+    ScriptHost *host;
 } ScriptModule;
 
-typedef struct ScriptHost {
+struct ScriptHost {
     IActiveScriptSite IActiveScriptSite_iface;
     IActiveScriptSiteWindow IActiveScriptSiteWindow_iface;
     IServiceProvider IServiceProvider_iface;
@@ -86,7 +89,7 @@ typedef struct ScriptHost {
     ScriptModule **modules;
 
     struct list named_items;
-} ScriptHost;
+};
 
 struct ScriptControl {
     IScriptControl IScriptControl_iface;
@@ -353,25 +356,6 @@ static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface)
     return ref;
 }
 
-static void release_script_engine(ScriptHost *host)
-{
-    if (host->script) {
-        IActiveScript_Close(host->script);
-        IActiveScript_Release(host->script);
-    }
-
-    if (host->parse)
-        IActiveScriptParse_Release(host->parse);
-    if (host->script_dispatch)
-        IDispatch_Release(host->script_dispatch);
-
-    host->script_dispatch = NULL;
-    host->parse = NULL;
-    host->script = NULL;
-
-    IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
-}
-
 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
 {
     ScriptHost *This = impl_from_IActiveScriptSite(iface);
@@ -570,6 +554,32 @@ static const IServiceProviderVtbl ServiceProviderVtbl = {
     ServiceProvider_QueryService
 };
 
+static void detach_module(ScriptModule *module)
+{
+    ScriptHost *host = module->host;
+
+    module->host = NULL;
+
+    if (--host->module_count)
+        return;
+
+    if (host->script) {
+        IActiveScript_Close(host->script);
+        IActiveScript_Release(host->script);
+    }
+
+    if (host->parse)
+        IActiveScriptParse_Release(host->parse);
+    if (host->script_dispatch)
+        IDispatch_Release(host->script_dispatch);
+
+    host->script_dispatch = NULL;
+    host->parse = NULL;
+    host->script = NULL;
+
+    IActiveScriptSite_Release(&host->IActiveScriptSite_iface);
+}
+
 static HRESULT WINAPI ScriptModule_QueryInterface(IScriptModule *iface, REFIID riid, void **ppv)
 {
     ScriptModule *This = impl_from_IScriptModule(iface);
@@ -608,7 +618,11 @@ static ULONG WINAPI ScriptModule_Release(IScriptModule *iface)
     TRACE("(%p) ref=%d\n", This, ref);
 
     if (!ref)
+    {
+        if (This->host)
+            detach_module(This);
         heap_free(This);
+    }
 
     return ref;
 }
@@ -754,7 +768,7 @@ static const IScriptModuleVtbl ScriptModuleVtbl = {
     ScriptModule_Run
 };
 
-static ScriptModule *create_module(void)
+static ScriptModule *create_module(ScriptHost *host)
 {
     ScriptModule *module;
 
@@ -762,18 +776,23 @@ static ScriptModule *create_module(void)
 
     module->IScriptModule_iface.lpVtbl = &ScriptModuleVtbl;
     module->ref = 1;
+    module->host = host;
     return module;
 }
 
-static void release_modules(ScriptHost *host)
+static void release_modules(ScriptHost *host, BOOL force_detach)
 {
-    unsigned int i;
+    /* Releasing the modules might destroy the host, so keep copies */
+    unsigned int i, module_count = host->module_count;
+    ScriptModule **modules = host->modules;
 
-    for (i = 0; i < host->module_count; i++)
-        IScriptModule_Release(&host->modules[i]->IScriptModule_iface);
+    for (i = 0; i < module_count; i++)
+    {
+        if (force_detach) detach_module(modules[i]);
+        IScriptModule_Release(&modules[i]->IScriptModule_iface);
+    }
 
-    host->module_count = 0;
-    heap_free(host->modules);
+    heap_free(modules);
 }
 
 static HRESULT WINAPI ScriptModuleCollection_QueryInterface(IScriptModuleCollection *iface, REFIID riid, void **ppv)
@@ -951,7 +970,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret)
     host->modules = heap_alloc_zero(sizeof(*host->modules));
     if (!host->modules) return E_OUTOFMEMORY;
 
-    host->modules[0] = create_module();
+    host->modules[0] = create_module(host);
     if (!host->modules[0]) {
         heap_free(host->modules);
         heap_free(host);
@@ -1002,8 +1021,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret)
     return S_OK;
 
 failed:
-    release_modules(host);
-    release_script_engine(host);
+    release_modules(host, FALSE);
     return hr;
 }
 
@@ -1081,10 +1099,7 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface)
         if (This->site)
             IOleClientSite_Release(This->site);
         if (This->host)
-        {
-            release_modules(This->host);
-            release_script_engine(This->host);
-        }
+            release_modules(This->host, FALSE);
         heap_free(This);
     }
 
@@ -1182,8 +1197,7 @@ static HRESULT WINAPI ScriptControl_put_Language(IScriptControl *iface, BSTR lan
         return CTL_E_INVALIDPROPERTYVALUE;
 
     if (This->host) {
-        release_modules(This->host);
-        release_script_engine(This->host);
+        release_modules(This->host, TRUE);
         This->host = NULL;
     }
 
-- 
2.21.0




More information about the wine-devel mailing list