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 e7ce691ba2c..e71e642b98f 100644 --- a/dlls/vbscript/interp.c +++ b/dlls/vbscript/interp.c @@ -2098,7 +2098,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 4062c3f826d..7d38297f12a 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