[PATCH 2/3] msscript.ocx: Implement IScriptControl::Run.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu Sep 26 09:43:44 CDT 2019


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

diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c
index 9cb8282..9319b5e 100644
--- a/dlls/msscript.ocx/msscript.c
+++ b/dlls/msscript.ocx/msscript.c
@@ -20,12 +20,14 @@
 
 #include "windows.h"
 #include "initguid.h"
+#include "dispex.h"
 #include "ole2.h"
 #include "olectl.h"
 #include "objsafe.h"
 #include "activscp.h"
 #include "rpcproxy.h"
 #include "msscript.h"
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
 
 #include "wine/debug.h"
 #include "wine/heap.h"
@@ -71,6 +73,7 @@ typedef struct ScriptHost {
 
     IActiveScript *script;
     IActiveScriptParse *parse;
+    IDispatch *script_dispatch;
     SCRIPTSTATE script_state;
     CLSID clsid;
 
@@ -200,6 +203,17 @@ static struct named_item *host_get_named_item(ScriptHost *host, const WCHAR *nam
     return NULL;
 }
 
+static HRESULT get_script_dispatch(struct ScriptControl *control, IDispatch **disp)
+{
+    if (!control->host->script_dispatch)
+    {
+        HRESULT hr = IActiveScript_GetScriptDispatch(control->host->script, NULL, &control->host->script_dispatch);
+        if (FAILED(hr)) return hr;
+    }
+    *disp = control->host->script_dispatch;
+    return S_OK;
+}
+
 static HRESULT set_script_state(ScriptHost *host, SCRIPTSTATE state)
 {
     HRESULT hr;
@@ -210,6 +224,19 @@ static HRESULT set_script_state(ScriptHost *host, SCRIPTSTATE state)
     return hr;
 }
 
+static HRESULT start_script(struct ScriptControl *control)
+{
+    HRESULT hr = S_OK;
+
+    if (!control->host || control->state != Initialized)
+        return E_FAIL;
+
+    if (control->host->script_state != SCRIPTSTATE_STARTED)
+        hr = set_script_state(control->host, SCRIPTSTATE_STARTED);
+
+    return hr;
+}
+
 static inline ScriptControl *impl_from_IScriptControl(IScriptControl *iface)
 {
     return CONTAINING_RECORD(iface, ScriptControl, IScriptControl_iface);
@@ -316,7 +343,10 @@ static void release_script_engine(ScriptHost *host)
 
     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;
 
@@ -539,6 +569,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret)
     host->ref = 1;
     host->script = NULL;
     host->parse = NULL;
+    host->script_dispatch = NULL;
     host->clsid = *clsid;
     list_init(&host->named_items);
 
@@ -982,15 +1013,8 @@ static HRESULT parse_script_text(ScriptControl *control, BSTR script_text, DWORD
     EXCEPINFO excepinfo;
     HRESULT hr;
 
-    if (!control->host || control->state != Initialized)
-        return E_FAIL;
-
-    if (control->host->script_state != SCRIPTSTATE_STARTED)
-    {
-        hr = set_script_state(control->host, SCRIPTSTATE_STARTED);
-        if (FAILED(hr))
-            return hr;
-    }
+    hr = start_script(control);
+    if (FAILED(hr)) return hr;
 
     hr = IActiveScriptParse_ParseScriptText(control->host->parse, script_text, NULL,
                                             NULL, NULL, 0, 1, flag, res, &excepinfo);
@@ -1032,8 +1056,74 @@ static HRESULT WINAPI ScriptControl_ExecuteStatement(IScriptControl *iface, BSTR
 static HRESULT WINAPI ScriptControl_Run(IScriptControl *iface, BSTR procedure_name, SAFEARRAY **parameters, VARIANT *res)
 {
     ScriptControl *This = impl_from_IScriptControl(iface);
-    FIXME("(%p)->(%s %p %p)\n", This, debugstr_w(procedure_name), parameters, res);
-    return E_NOTIMPL;
+    IDispatchEx *dispex;
+    IDispatch *disp;
+    SAFEARRAY *sa;
+    DISPPARAMS dp;
+    DISPID dispid;
+    HRESULT hr;
+    UINT i = 0;
+
+    TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(procedure_name), parameters, res);
+
+    if (!parameters || !res) return E_POINTER;
+    if (!(sa = *parameters)) return E_POINTER;
+
+    if (sa->cDims == 0) return DISP_E_BADINDEX;
+    if (!(sa->fFeatures & FADF_VARIANT)) return DISP_E_BADVARTYPE;
+
+    hr = start_script(This);
+    if (FAILED(hr)) return hr;
+
+    dp.cArgs = sa->rgsabound[0].cElements;
+    dp.rgdispidNamedArgs = NULL;
+    dp.cNamedArgs = 0;
+
+    dp.rgvarg = heap_alloc(dp.cArgs * sizeof(*dp.rgvarg));
+    if (!dp.rgvarg) return E_OUTOFMEMORY;
+
+    hr = SafeArrayLock(sa);
+    if (FAILED(hr)) goto err;
+
+    for (i = 0; i < dp.cArgs; i++)
+    {
+        /* The DISPPARAMS are stored in reverse order */
+        VARIANT *src = (VARIANT*)((char*)(sa->pvData) + (dp.cArgs - i - 1) * sa->cbElements);
+
+        V_VT(&dp.rgvarg[i]) = VT_EMPTY;
+        hr = VariantCopy(&dp.rgvarg[i], src);
+        if (FAILED(hr))
+        {
+            SafeArrayUnlock(sa);
+            goto err;
+        }
+    }
+    SafeArrayUnlock(sa);
+
+    hr = get_script_dispatch(This, &disp);
+    if (FAILED(hr)) goto err;
+
+    hr = IDispatch_GetIDsOfNames(disp, &IID_NULL, &procedure_name, 1, LOCALE_USER_DEFAULT, &dispid);
+    if (FAILED(hr)) goto err;
+
+    hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    if (FAILED(hr))
+    {
+        hr = IDispatch_Invoke(disp, dispid, &IID_NULL, LOCALE_USER_DEFAULT,
+                              DISPATCH_METHOD, &dp, res, NULL, NULL);
+    }
+    else
+    {
+        hr = IDispatchEx_InvokeEx(dispex, dispid, LOCALE_USER_DEFAULT,
+                                  DISPATCH_METHOD, &dp, res, NULL, NULL);
+        IDispatchEx_Release(dispex);
+    }
+
+err:
+    while (i--)
+        VariantClear(&dp.rgvarg[i]);
+    heap_free(dp.rgvarg);
+    return hr;
 }
 
 static const IScriptControlVtbl ScriptControlVtbl = {
-- 
2.21.0




More information about the wine-devel mailing list