From 4aaaae158611da4a502ca8d6b364ab6bf82cbf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= Date: Mon, 24 Aug 2020 17:56:10 +0300 Subject: [PATCH] msscript.ocx: Add the ScriptError stub implementation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- 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 d4930654290..c92a86a4931 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 085913a48eb..9bbbe4c94d5 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, ¶ms, &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, ¶ms, 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, ¶ms, &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;