msscript.ocx: Add the ScriptError stub implementation.

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@gmail.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2020-08-24 17:56:10 +03:00 committed by Alexandre Julliard
parent aaea13a128
commit 4aaaae1586
2 changed files with 256 additions and 23 deletions

View File

@ -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);

View File

@ -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;