From: Francis De Brabandere <francisdb@gmail.com> Native VarImp returns VT_NULL for UI1 0xFF Imp Null via the three- valued all-ones rule, but native VBScript keeps UI1 width and returns the bitwise ~left. Handle the narrow case directly in interp_imp. --- dlls/vbscript/interp.c | 13 ++++++++++++- dlls/vbscript/tests/lang.vbs | 12 +++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/dlls/vbscript/interp.c b/dlls/vbscript/interp.c index ba530fca38c..c92006b15d6 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -2103,7 +2103,18 @@ static HRESULT interp_imp(exec_ctx_t *ctx) hres = stack_pop_val(ctx, &l); if(SUCCEEDED(hres)) { - hres = VarImp(l.v, r.v, &v); + /* Native VarImp returns VT_NULL for UI1 0xFF Imp Null under the + * three-valued "all-ones Imp unknown = unknown" rule, but native + * VBScript keeps UI1 width and returns the bitwise complement of + * the left operand. Handle UI1 Imp Null directly. */ + if ((V_VT(l.v) & VT_TYPEMASK) == VT_UI1 && + (V_VT(r.v) & VT_TYPEMASK) == VT_NULL) { + V_VT(&v) = VT_UI1; + V_UI1(&v) = ~V_UI1(l.v); + hres = S_OK; + } else { + hres = VarImp(l.v, r.v, &v); + } release_val(&l); } release_val(&r); diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 708663732a1..a6184b825b8 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -213,9 +213,19 @@ Call ok((True Or Null) = True, "True Or Null is not True") Call ok(isNull(False Or Null), "False Or Null is not Null") Call ok(isNull(CInt(5) Xor Null), "CInt(5) Xor Null is not Null") Call ok(isNull(CInt(5) Eqv Null), "CInt(5) Eqv Null is not Null") -Call ok(isNull(CByte(255) Imp Null), "CByte(255) Imp Null is not Null") Call ok((Not CLng(0)) = -1, "Not CLng(0) is not -1") +' VBScript-specific: for VT_UI1 Imp VT_NULL, native VBScript keeps UI1 +' width and returns the bitwise complement of the left operand, rather +' than applying VarImp's three-valued "all-ones Imp unknown = unknown" +' rule (which returns VT_NULL at the C level for UI1 0xFF). interp_imp +' has a narrow special case to match this native behavior. +Call ok((CByte(0) Imp Null) = 255, "CByte(0) Imp Null is not 255") +Call ok(getVT(CByte(0) Imp Null) = "VT_UI1", "getVT(CByte(0) Imp Null) = " & getVT(CByte(0) Imp Null)) +Call ok((CByte(170) Imp Null) = 85, "CByte(170) Imp Null is not 85") +Call ok((CByte(255) Imp Null) = 0, "CByte(255) Imp Null is not 0") +Call ok(getVT(CByte(255) Imp Null) = "VT_UI1", "getVT(CByte(255) Imp Null) = " & getVT(CByte(255) Imp Null)) + Call ok(2 >= 1, "! 2 >= 1") Call ok(2 >= 2, "! 2 >= 2") Call ok(2 => 1, "! 2 => 1") -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10673