wbemprox: Allow string values in boolean comparisons.

This commit is contained in:
Hans Leidekker 2014-01-28 13:26:16 +01:00 committed by Alexandre Julliard
parent 0e9f46d074
commit 6a042307a5
3 changed files with 107 additions and 12 deletions

View File

@ -806,12 +806,14 @@ static const struct record_stdregprov data_stdregprov[] =
static BOOL match_row( const struct table *table, UINT row, const struct expr *cond, enum fill_status *status )
{
LONGLONG val;
UINT type;
if (!cond)
{
*status = FILL_STATUS_UNFILTERED;
return TRUE;
}
if (eval_cond( table, row, cond, &val ) != S_OK)
if (eval_cond( table, row, cond, &val, &type ) != S_OK)
{
*status = FILL_STATUS_FAILED;
return FALSE;

View File

@ -114,16 +114,93 @@ static inline BOOL is_strcmp( const struct complex_expr *expr )
(expr->left->type == EXPR_SVAL && expr->right->type == EXPR_PROPVAL));
}
static inline BOOL is_boolcmp( const struct complex_expr *expr, UINT ltype, UINT rtype )
{
if (ltype == CIM_BOOLEAN && expr->left->type == EXPR_PROPVAL &&
(expr->right->type == EXPR_SVAL || expr->right->type == EXPR_BVAL)) return TRUE;
else if (rtype == CIM_BOOLEAN && expr->right->type == EXPR_PROPVAL &&
(expr->left->type == EXPR_SVAL || expr->left->type == EXPR_BVAL)) return TRUE;
return FALSE;
}
static HRESULT eval_boolcmp( UINT op, LONGLONG lval, LONGLONG rval, UINT ltype, UINT rtype, LONGLONG *val )
{
static const WCHAR trueW[] = {'T','r','u','e',0};
if (ltype == CIM_STRING) lval = !strcmpiW( (const WCHAR *)(INT_PTR)lval, trueW ) ? -1 : 0;
else if (rtype == CIM_STRING) rval = !strcmpiW( (const WCHAR *)(INT_PTR)rval, trueW ) ? -1 : 0;
switch (op)
{
case OP_EQ:
*val = (lval == rval);
break;
case OP_NE:
*val = (lval != rval);
break;
default:
ERR("unhandled operator %u\n", op);
return WBEM_E_INVALID_QUERY;
}
return S_OK;
}
static UINT resolve_type( UINT left, UINT right )
{
switch (left)
{
case CIM_SINT8:
case CIM_SINT16:
case CIM_SINT32:
case CIM_SINT64:
case CIM_UINT8:
case CIM_UINT16:
case CIM_UINT32:
case CIM_UINT64:
switch (right)
{
case CIM_SINT8:
case CIM_SINT16:
case CIM_SINT32:
case CIM_SINT64:
case CIM_UINT8:
case CIM_UINT16:
case CIM_UINT32:
case CIM_UINT64:
return CIM_UINT64;
default: break;
}
case CIM_STRING:
if (right == CIM_STRING) return CIM_STRING;
break;
case CIM_BOOLEAN:
if (right == CIM_BOOLEAN) return CIM_BOOLEAN;
break;
default:
break;
}
return CIM_ILLEGAL;
}
static HRESULT eval_binary( const struct table *table, UINT row, const struct complex_expr *expr,
LONGLONG *val )
LONGLONG *val, UINT *type )
{
HRESULT lret, rret;
LONGLONG lval, rval;
UINT ltype, rtype;
lret = eval_cond( table, row, expr->left, &lval );
rret = eval_cond( table, row, expr->right, &rval );
lret = eval_cond( table, row, expr->left, &lval, &ltype );
rret = eval_cond( table, row, expr->right, &rval, &rtype );
if (lret != S_OK || rret != S_OK) return WBEM_E_INVALID_QUERY;
*type = resolve_type( ltype, rtype );
if (is_boolcmp( expr, ltype, rtype ))
return eval_boolcmp( expr->op, lval, rval, ltype, rtype, val );
if (is_strcmp( expr ))
{
const WCHAR *lstr = (const WCHAR *)(INT_PTR)lval;
@ -165,7 +242,7 @@ static HRESULT eval_binary( const struct table *table, UINT row, const struct co
}
static HRESULT eval_unary( const struct table *table, UINT row, const struct complex_expr *expr,
LONGLONG *val )
LONGLONG *val, UINT *type )
{
HRESULT hr;
@ -192,11 +269,13 @@ static HRESULT eval_unary( const struct table *table, UINT row, const struct com
ERR("unknown operator %u\n", expr->op);
return WBEM_E_INVALID_QUERY;
}
*type = table->columns[column].type & CIM_TYPE_MASK;
return S_OK;
}
static HRESULT eval_propval( const struct table *table, UINT row, const struct property *propval,
LONGLONG *val )
LONGLONG *val, UINT *type )
{
HRESULT hr;
@ -206,31 +285,44 @@ static HRESULT eval_propval( const struct table *table, UINT row, const struct p
if (hr != S_OK)
return hr;
*type = table->columns[column].type & CIM_TYPE_MASK;
return get_value( table, row, column, val );
}
HRESULT eval_cond( const struct table *table, UINT row, const struct expr *cond, LONGLONG *val )
HRESULT eval_cond( const struct table *table, UINT row, const struct expr *cond, LONGLONG *val, UINT *type )
{
if (!cond)
{
*val = 1;
*type = CIM_UINT64;
return S_OK;
}
switch (cond->type)
{
case EXPR_COMPLEX:
return eval_binary( table, row, &cond->u.expr, val );
return eval_binary( table, row, &cond->u.expr, val, type );
case EXPR_UNARY:
return eval_unary( table, row, &cond->u.expr, val );
return eval_unary( table, row, &cond->u.expr, val, type );
case EXPR_PROPVAL:
return eval_propval( table, row, cond->u.propval, val );
return eval_propval( table, row, cond->u.propval, val, type );
case EXPR_SVAL:
*val = (INT_PTR)cond->u.sval;
*type = CIM_STRING;
return S_OK;
case EXPR_IVAL:
*val = cond->u.ival;
*type = CIM_UINT64;
return S_OK;
case EXPR_BVAL:
*val = cond->u.ival;
*type = CIM_BOOLEAN;
return S_OK;
default:
ERR("invalid expression type\n");
break;
@ -257,6 +349,7 @@ HRESULT execute_view( struct view *view )
{
HRESULT hr;
LONGLONG val = 0;
UINT type;
if (j >= len)
{
@ -265,7 +358,7 @@ HRESULT execute_view( struct view *view )
if (!(tmp = heap_realloc( view->result, len * sizeof(UINT) ))) return E_OUTOFMEMORY;
view->result = tmp;
}
if ((hr = eval_cond( view->table, i, view->cond, &val )) != S_OK) return hr;
if ((hr = eval_cond( view->table, i, view->cond, &val, &type )) != S_OK) return hr;
if (val) view->result[j++] = i;
}
view->count = j;

View File

@ -186,7 +186,7 @@ void free_row_values( const struct table *, UINT ) DECLSPEC_HIDDEN;
void clear_table( struct table * ) DECLSPEC_HIDDEN;
void free_table( struct table * ) DECLSPEC_HIDDEN;
UINT get_type_size( CIMTYPE ) DECLSPEC_HIDDEN;
HRESULT eval_cond( const struct table *, UINT, const struct expr *, LONGLONG * ) DECLSPEC_HIDDEN;
HRESULT eval_cond( const struct table *, UINT, const struct expr *, LONGLONG *, UINT * ) DECLSPEC_HIDDEN;
HRESULT get_column_index( const struct table *, const WCHAR *, UINT * ) DECLSPEC_HIDDEN;
HRESULT get_value( const struct table *, UINT, UINT, LONGLONG * ) DECLSPEC_HIDDEN;
BSTR get_value_bstr( const struct table *, UINT, UINT ) DECLSPEC_HIDDEN;