From 1c194f3b21967024b10de5b2f6b72947d687731b Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 27 Jan 2020 14:25:39 +0100 Subject: [PATCH] vbscript: Fix VT_UNKNOWN handling in set statements. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/vbscript/interp.c | 12 +++++------ dlls/vbscript/tests/lang.vbs | 6 ++++++ dlls/vbscript/tests/run.c | 39 +++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index 9c075355174..333fe0f6bdb 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -458,22 +458,22 @@ static HRESULT stack_assume_disp(exec_ctx_t *ctx, unsigned n, IDispatch **disp) { VARIANT *v = stack_top(ctx, n), *ref; - if(V_VT(v) != VT_DISPATCH) { + if(V_VT(v) != VT_DISPATCH && (disp || V_VT(v) != VT_UNKNOWN)) { if(V_VT(v) != (VT_VARIANT|VT_BYREF)) { FIXME("not supported type: %s\n", debugstr_variant(v)); return E_FAIL; } ref = V_VARIANTREF(v); - if(V_VT(ref) != VT_DISPATCH) { + if(V_VT(ref) != VT_DISPATCH && (disp || V_VT(ref) != VT_UNKNOWN)) { FIXME("not disp %s\n", debugstr_variant(ref)); return E_FAIL; } - V_VT(v) = VT_DISPATCH; - V_DISPATCH(v) = V_DISPATCH(ref); - if(V_DISPATCH(v)) - IDispatch_AddRef(V_DISPATCH(v)); + V_VT(v) = V_VT(ref); + V_UNKNOWN(v) = V_UNKNOWN(ref); + if(V_UNKNOWN(v)) + IUnknown_AddRef(V_UNKNOWN(v)); } if(disp) diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 8007823394d..f527b3411be 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -1197,6 +1197,12 @@ Call ok(obj.Test1 = 6, "obj.Test1 is not 6") obj.AddToTest1(5) Call ok(obj.Test1 = 11, "obj.Test1 is not 11") +set obj = unkObj +set x = obj +call ok(getVT(obj) = "VT_UNKNOWN*", "getVT(obj) = " & getVT(obj)) +call ok(getVT(x) = "VT_UNKNOWN*", "getVT(x) = " & getVT(x)) +call ok(getVT(unkObj) = "VT_UNKNOWN", "getVT(unkObj) = " & getVT(unkObj)) + ' Array tests Call ok(getVT(arr) = "VT_EMPTY*", "getVT(arr) = " & getVT(arr)) diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 015f2b816ae..8acf220f9fe 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -144,6 +144,7 @@ DEFINE_EXPECT(OnLeaveScript); #define DISPID_GLOBAL_TESTERROROBJECT 1023 #define DISPID_GLOBAL_THROWWITHDESC 1024 #define DISPID_GLOBAL_PROPARGSET 1025 +#define DISPID_GLOBAL_UNKOBJ 1026 #define DISPID_TESTOBJ_PROPGET 2000 #define DISPID_TESTOBJ_PROPPUT 2001 @@ -214,6 +215,8 @@ static const char *vt2a(VARIANT *v) return "VT_BSTR"; case VT_DISPATCH: return "VT_DISPATCH"; + case VT_UNKNOWN: + return "VT_UNKNOWN"; case VT_BOOL: return "VT_BOOL"; case VT_ARRAY|VT_VARIANT: @@ -595,6 +598,35 @@ static void _test_grfdex(unsigned line, DWORD grfdex, DWORD expect) static IDispatchEx enumDisp; +static HRESULT WINAPI unkObj_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown)) { + *ppv = iface; + return S_OK; + } + + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI unkObj_AddRef(IUnknown *iface) +{ + return 2; +} + +static ULONG WINAPI unkObj_Release(IUnknown *iface) +{ + return 1; +} + +static const IUnknownVtbl unkObjVtbl = { + unkObj_QueryInterface, + unkObj_AddRef, + unkObj_Release +}; + +static IUnknown unkObj = { &unkObjVtbl }; + static HRESULT WINAPI EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) { if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumVARIANT)) { @@ -1138,7 +1170,8 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD { L"throwInt", DISPID_GLOBAL_THROWINT }, { L"testOptionalArg", DISPID_GLOBAL_TESTOPTIONALARG }, { L"testErrorObject", DISPID_GLOBAL_TESTERROROBJECT }, - { L"throwWithDesc", DISPID_GLOBAL_THROWWITHDESC } + { L"throwWithDesc", DISPID_GLOBAL_THROWWITHDESC }, + { L"unkObj", DISPID_GLOBAL_UNKOBJ } }; test_grfdex(grfdex, fdexNameCaseInsensitive); @@ -1657,6 +1690,10 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, ok(hres == S_OK, "Invoke failed: %08x\n", hres); return S_OK; } + case DISPID_GLOBAL_UNKOBJ: + V_VT(pvarRes) = VT_UNKNOWN; + V_UNKNOWN(pvarRes) = &unkObj; + return S_OK; } ok(0, "unexpected call %d\n", id);