[PATCH 01/11] msscript.ocx: Add the ScriptError stub implementation.

Gabriel Ivăncescu gabrielopcode at gmail.com
Mon Aug 24 09:56:10 CDT 2020


The error object has to be separate from the control, as it can be referenced
while the control is released. It is also available even without a script
host, and in fact the same object will be used (same address) when a host
is instantiated.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/msscript.ocx/msscript.c       | 240 ++++++++++++++++++++++++++++-
 dlls/msscript.ocx/tests/msscript.c |  39 +++--
 2 files changed, 256 insertions(+), 23 deletions(-)

diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c
index d493065..c92a86a 100644
--- a/dlls/msscript.ocx/msscript.c
+++ b/dlls/msscript.ocx/msscript.c
@@ -119,6 +119,11 @@ struct procedure_enum {
     ScriptProcedureCollection *procedures;
 };
 
+typedef struct {
+    IScriptError IScriptError_iface;
+    LONG ref;
+} ScriptError;
+
 struct ScriptHost {
     IActiveScriptSite IActiveScriptSite_iface;
     IActiveScriptSiteWindow IActiveScriptSiteWindow_iface;
@@ -164,12 +169,14 @@ struct ScriptControl {
     IScriptModuleCollection IScriptModuleCollection_iface;
 
     ScriptHost *host;
+    ScriptError *error;
 };
 
 static HINSTANCE msscript_instance;
 
 typedef enum tid_t {
     IScriptControl_tid,
+    IScriptError_tid,
     IScriptModuleCollection_tid,
     IScriptModule_tid,
     IScriptProcedureCollection_tid,
@@ -182,6 +189,7 @@ static ITypeInfo *typeinfos[LAST_tid];
 
 static REFIID tid_ids[] = {
     &IID_IScriptControl,
+    &IID_IScriptError,
     &IID_IScriptModuleCollection,
     &IID_IScriptModule,
     &IID_IScriptProcedureCollection,
@@ -516,6 +524,11 @@ static inline ScriptModule *impl_from_IScriptModule(IScriptModule *iface)
     return CONTAINING_RECORD(iface, ScriptModule, IScriptModule_iface);
 }
 
+static inline ScriptError *impl_from_IScriptError(IScriptError *iface)
+{
+    return CONTAINING_RECORD(iface, ScriptError, IScriptError_iface);
+}
+
 static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
 {
     return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
@@ -2086,6 +2099,212 @@ static const IScriptModuleCollectionVtbl ScriptModuleCollectionVtbl = {
     ScriptModuleCollection_Add
 };
 
+static HRESULT WINAPI ScriptError_QueryInterface(IScriptError *iface, REFIID riid, void **ppv)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    if (IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IUnknown, riid) ||
+        IsEqualGUID(&IID_IScriptError, riid))
+    {
+        *ppv = &This->IScriptError_iface;
+    }
+    else
+    {
+        WARN("unsupported interface: (%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown*)*ppv);
+    return S_OK;
+}
+
+static ULONG WINAPI ScriptError_AddRef(IScriptError *iface)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+    LONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) ref=%d\n", This, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI ScriptError_Release(IScriptError *iface)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) ref=%d\n", This, ref);
+
+    if (!ref)
+    {
+        heap_free(This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI ScriptError_GetTypeInfoCount(IScriptError *iface, UINT *pctinfo)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    TRACE("(%p)->(%p)\n", This, pctinfo);
+
+    *pctinfo = 1;
+    return S_OK;
+}
+
+static HRESULT WINAPI ScriptError_GetTypeInfo(IScriptError *iface, UINT iTInfo,
+        LCID lcid, ITypeInfo **ppTInfo)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
+
+    return get_typeinfo(IScriptError_tid, ppTInfo);
+}
+
+static HRESULT WINAPI ScriptError_GetIDsOfNames(IScriptError *iface, REFIID riid,
+        LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
+
+    hr = get_typeinfo(IScriptError_tid, &typeinfo);
+    if (SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
+        ITypeInfo_Release(typeinfo);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI ScriptError_Invoke(IScriptError *iface, DISPID dispIdMember,
+        REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
+        EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
+           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+
+    hr = get_typeinfo(IScriptError_tid, &typeinfo);
+    if(SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_Invoke(typeinfo, iface, dispIdMember, wFlags,
+                              pDispParams, pVarResult, pExcepInfo, puArgErr);
+        ITypeInfo_Release(typeinfo);
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI ScriptError_get_Number(IScriptError *iface, LONG *plNumber)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, plNumber);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_get_Source(IScriptError *iface, BSTR *pbstrSource)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, pbstrSource);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_get_Description(IScriptError *iface, BSTR *pbstrDescription)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, pbstrDescription);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_get_HelpFile(IScriptError *iface, BSTR *pbstrHelpFile)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, pbstrHelpFile);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_get_HelpContext(IScriptError *iface, LONG *plHelpContext)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, plHelpContext);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_get_Text(IScriptError *iface, BSTR *pbstrText)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, pbstrText);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_get_Line(IScriptError *iface, LONG *plLine)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, plLine);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_get_Column(IScriptError *iface, LONG *plColumn)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->(%p)\n", This, plColumn);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ScriptError_Clear(IScriptError *iface)
+{
+    ScriptError *This = impl_from_IScriptError(iface);
+
+    FIXME("(%p)->()\n", This);
+
+    return E_NOTIMPL;
+}
+
+static const IScriptErrorVtbl ScriptErrorVtbl = {
+    ScriptError_QueryInterface,
+    ScriptError_AddRef,
+    ScriptError_Release,
+    ScriptError_GetTypeInfoCount,
+    ScriptError_GetTypeInfo,
+    ScriptError_GetIDsOfNames,
+    ScriptError_Invoke,
+    ScriptError_get_Number,
+    ScriptError_get_Source,
+    ScriptError_get_Description,
+    ScriptError_get_HelpFile,
+    ScriptError_get_HelpContext,
+    ScriptError_get_Text,
+    ScriptError_get_Line,
+    ScriptError_get_Column,
+    ScriptError_Clear
+};
+
 static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret)
 {
     IObjectSafety *objsafety;
@@ -2233,6 +2452,7 @@ static ULONG WINAPI ScriptControl_Release(IScriptControl *iface)
             release_modules(This, FALSE);
             IActiveScriptSite_Release(&This->host->IActiveScriptSite_iface);
         }
+        IScriptError_Release(&This->error->IScriptError_iface);
         heap_free(This);
     }
 
@@ -2513,8 +2733,14 @@ static HRESULT WINAPI ScriptControl_get_Modules(IScriptControl *iface, IScriptMo
 static HRESULT WINAPI ScriptControl_get_Error(IScriptControl *iface, IScriptError **p)
 {
     ScriptControl *This = impl_from_IScriptControl(iface);
-    FIXME("(%p)->(%p)\n", This, p);
-    return E_NOTIMPL;
+
+    TRACE("(%p)->(%p)\n", This, p);
+
+    if (!p) return E_POINTER;
+
+    *p = &This->error->IScriptError_iface;
+    IScriptError_AddRef(*p);
+    return S_OK;
 }
 
 static HRESULT WINAPI ScriptControl_get_CodeObject(IScriptControl *iface, IDispatch **p)
@@ -3543,6 +3769,13 @@ static HRESULT WINAPI ScriptControl_CreateInstance(IClassFactory *iface, IUnknow
     if(!script_control)
         return E_OUTOFMEMORY;
 
+    script_control->error = heap_alloc_zero(sizeof(*script_control->error));
+    if(!script_control->error)
+    {
+        heap_free(script_control);
+        return E_OUTOFMEMORY;
+    }
+
     script_control->IScriptControl_iface.lpVtbl = &ScriptControlVtbl;
     script_control->IPersistStreamInit_iface.lpVtbl = &PersistStreamInitVtbl;
     script_control->IOleObject_iface.lpVtbl = &OleObjectVtbl;
@@ -3557,6 +3790,9 @@ static HRESULT WINAPI ScriptControl_CreateInstance(IClassFactory *iface, IUnknow
     script_control->allow_ui = VARIANT_TRUE;
     script_control->use_safe_subset = VARIANT_FALSE;
 
+    script_control->error->IScriptError_iface.lpVtbl = &ScriptErrorVtbl;
+    script_control->error->ref = 1;
+
     ConnectionPoint_Init(&script_control->cp_scsource, script_control, &DIID_DScriptControlSource);
     ConnectionPoint_Init(&script_control->cp_propnotif, script_control, &IID_IPropertyNotifySink);
 
diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c
index 085913a..9bbbe4c 100644
--- a/dlls/msscript.ocx/tests/msscript.c
+++ b/dlls/msscript.ocx/tests/msscript.c
@@ -2075,15 +2075,12 @@ static void _check_error(IScriptControl *sc, LONG exp_num, int line)
 
     hr = IScriptControl_get_Error(sc, &script_err);
     ok_(__FILE__,line)(hr == S_OK, "IScriptControl_get_Error failed: 0x%08x.\n", hr);
-    if (SUCCEEDED(hr))
-    {
-        error_num = 0xdeadbeef;
-        hr = IScriptError_get_Number(script_err, &error_num);
-        ok_(__FILE__,line)(hr == S_OK, "IScriptError_get_Number failed: 0x%08x.\n", hr);
-        ok_(__FILE__,line)(error_num == exp_num, "got wrong error number: %d, expected %d.\n",
-                           error_num, exp_num);
-        IScriptError_Release(script_err);
-    }
+    error_num = 0xdeadbeef;
+    hr = IScriptError_get_Number(script_err, &error_num);
+    todo_wine ok_(__FILE__,line)(hr == S_OK, "IScriptError_get_Number failed: 0x%08x.\n", hr);
+    todo_wine ok_(__FILE__,line)(error_num == exp_num, "got wrong error number: %d, expected %d.\n",
+                       error_num, exp_num);
+    IScriptError_Release(script_err);
 }
 
 static void test_IScriptControl_Eval(void)
@@ -2112,7 +2109,7 @@ static void test_IScriptControl_Eval(void)
     ok(hr == E_FAIL, "IScriptControl_Eval returned: 0x%08x.\n", hr);
     ok((V_VT(&var) == VT_EMPTY) && (V_I4(&var) == 0xdeadbeef), "V_VT(var) = %d, V_I4(var) = %d.\n",
        V_VT(&var), V_I4(&var));
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
 
     script_str = SysAllocString(L"1 + 1");
     V_VT(&var) = VT_NULL;
@@ -2160,7 +2157,7 @@ static void test_IScriptControl_Eval(void)
     ok(V_I4(&var) == 0xdeadbeef || broken(V_I4(&var) == 0) /* after Win8 */,
        "V_I4(var) = %d.\n", V_I4(&var));
     SysFreeString(script_str);
-    todo_wine CHECK_ERROR(sc, 1004);
+    CHECK_ERROR(sc, 1004);
 
     script_str = SysAllocString(L"var2 = var1 + var2");
     V_VT(&var) = VT_NULL;
@@ -2287,13 +2284,13 @@ static void test_IScriptControl_AddCode(void)
     hr = IScriptControl_AddCode(sc, code_str);
     ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr);
     SysFreeString(code_str);
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
 
     code_str = SysAllocString(L"invalid syntax");
     hr = IScriptControl_AddCode(sc, code_str);
     todo_wine ok(hr == 0x800a03ec, "IScriptControl_AddCode returned: 0x%08x.\n", hr);
     SysFreeString(code_str);
-    todo_wine CHECK_ERROR(sc, 1004);
+    CHECK_ERROR(sc, 1004);
 
     IScriptControl_Release(sc);
 
@@ -2388,13 +2385,13 @@ static void test_IScriptControl_ExecuteStatement(void)
     hr = IScriptControl_ExecuteStatement(sc, str);
     ok(hr == S_OK, "IScriptControl_ExecuteStatement failed: 0x%08x.\n", hr);
     SysFreeString(str);
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
 
     str = SysAllocString(L"invalid syntax");
     hr = IScriptControl_ExecuteStatement(sc, str);
     todo_wine ok(hr == 0x800a03ec, "IScriptControl_ExecuteStatement returned: 0x%08x.\n", hr);
     SysFreeString(str);
-    todo_wine CHECK_ERROR(sc, 1004);
+    CHECK_ERROR(sc, 1004);
 
     IScriptControl_Release(sc);
 
@@ -2500,13 +2497,13 @@ static void test_IScriptControl_Run(void)
     str = SysAllocString(L"foobar");
     hr = IScriptControl_Run(sc, str, &params, &var);
     ok(hr == DISP_E_UNKNOWNNAME, "IScriptControl_Run failed: 0x%08x.\n", hr);
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
     SysFreeString(str);
 
     str = SysAllocString(L"function subtract(a, b) { return a - b; }\n");
     hr = IScriptControl_AddCode(sc, str);
     ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr);
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
     SysFreeString(str);
 
     str = SysAllocString(L"Subtract");
@@ -2517,12 +2514,12 @@ static void test_IScriptControl_Run(void)
     str = SysAllocString(L"subtract");
     hr = IScriptControl_Run(sc, str, &params, NULL);
     ok(hr == E_POINTER, "IScriptControl_Run failed: 0x%08x.\n", hr);
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
 
     hr = IScriptControl_Run(sc, str, &params, &var);
     ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr);
     ok((V_VT(&var) == VT_I4) && (V_I4(&var) == 7), "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var));
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
     SafeArrayDestroy(params);
 
     /* The array's other dimensions are ignored */
@@ -3340,7 +3337,7 @@ static void test_IScriptControl_get_Procedures(void)
     );
     hr = IScriptControl_AddCode(sc, str);
     ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr);
-    todo_wine CHECK_ERROR(sc, 0);
+    CHECK_ERROR(sc, 0);
     SysFreeString(str);
 
     hr = IScriptProcedureCollection_get_Count(procs, &count);
@@ -3480,7 +3477,7 @@ static void test_IScriptControl_get_Procedures(void)
         hr = IScriptControl_AddCode(sc, str);
         ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr);
         SysFreeString(str);
-        todo_wine CHECK_ERROR(sc, 0);
+        CHECK_ERROR(sc, 0);
         CHECK_CALLED(ParseScriptText);
 
         GetScriptDispatch_expected_name = NULL;
-- 
2.21.0




More information about the wine-devel mailing list