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 ) static BOOL match_row( const struct table *table, UINT row, const struct expr *cond, enum fill_status *status )
{ {
LONGLONG val; LONGLONG val;
UINT type;
if (!cond) if (!cond)
{ {
*status = FILL_STATUS_UNFILTERED; *status = FILL_STATUS_UNFILTERED;
return TRUE; 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; *status = FILL_STATUS_FAILED;
return FALSE; 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)); (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, static HRESULT eval_binary( const struct table *table, UINT row, const struct complex_expr *expr,
LONGLONG *val ) LONGLONG *val, UINT *type )
{ {
HRESULT lret, rret; HRESULT lret, rret;
LONGLONG lval, rval; LONGLONG lval, rval;
UINT ltype, rtype;
lret = eval_cond( table, row, expr->left, &lval ); lret = eval_cond( table, row, expr->left, &lval, &ltype );
rret = eval_cond( table, row, expr->right, &rval ); rret = eval_cond( table, row, expr->right, &rval, &rtype );
if (lret != S_OK || rret != S_OK) return WBEM_E_INVALID_QUERY; 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 )) if (is_strcmp( expr ))
{ {
const WCHAR *lstr = (const WCHAR *)(INT_PTR)lval; 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, static HRESULT eval_unary( const struct table *table, UINT row, const struct complex_expr *expr,
LONGLONG *val ) LONGLONG *val, UINT *type )
{ {
HRESULT hr; 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); ERR("unknown operator %u\n", expr->op);
return WBEM_E_INVALID_QUERY; return WBEM_E_INVALID_QUERY;
} }
*type = table->columns[column].type & CIM_TYPE_MASK;
return S_OK; return S_OK;
} }
static HRESULT eval_propval( const struct table *table, UINT row, const struct property *propval, static HRESULT eval_propval( const struct table *table, UINT row, const struct property *propval,
LONGLONG *val ) LONGLONG *val, UINT *type )
{ {
HRESULT hr; HRESULT hr;
@ -206,31 +285,44 @@ static HRESULT eval_propval( const struct table *table, UINT row, const struct p
if (hr != S_OK) if (hr != S_OK)
return hr; return hr;
*type = table->columns[column].type & CIM_TYPE_MASK;
return get_value( table, row, column, val ); 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) if (!cond)
{ {
*val = 1; *val = 1;
*type = CIM_UINT64;
return S_OK; return S_OK;
} }
switch (cond->type) switch (cond->type)
{ {
case EXPR_COMPLEX: 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: 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: 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: case EXPR_SVAL:
*val = (INT_PTR)cond->u.sval; *val = (INT_PTR)cond->u.sval;
*type = CIM_STRING;
return S_OK; return S_OK;
case EXPR_IVAL: case EXPR_IVAL:
*val = cond->u.ival;
*type = CIM_UINT64;
return S_OK;
case EXPR_BVAL: case EXPR_BVAL:
*val = cond->u.ival; *val = cond->u.ival;
*type = CIM_BOOLEAN;
return S_OK; return S_OK;
default: default:
ERR("invalid expression type\n"); ERR("invalid expression type\n");
break; break;
@ -257,6 +349,7 @@ HRESULT execute_view( struct view *view )
{ {
HRESULT hr; HRESULT hr;
LONGLONG val = 0; LONGLONG val = 0;
UINT type;
if (j >= len) 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; if (!(tmp = heap_realloc( view->result, len * sizeof(UINT) ))) return E_OUTOFMEMORY;
view->result = tmp; 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; if (val) view->result[j++] = i;
} }
view->count = j; 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 clear_table( struct table * ) DECLSPEC_HIDDEN;
void free_table( struct table * ) DECLSPEC_HIDDEN; void free_table( struct table * ) DECLSPEC_HIDDEN;
UINT get_type_size( CIMTYPE ) 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_column_index( const struct table *, const WCHAR *, UINT * ) DECLSPEC_HIDDEN;
HRESULT get_value( const struct table *, UINT, UINT, LONGLONG * ) DECLSPEC_HIDDEN; HRESULT get_value( const struct table *, UINT, UINT, LONGLONG * ) DECLSPEC_HIDDEN;
BSTR get_value_bstr( const struct table *, UINT, UINT ) DECLSPEC_HIDDEN; BSTR get_value_bstr( const struct table *, UINT, UINT ) DECLSPEC_HIDDEN;