From 3e52cea324af31fa7436615db2602fbb6984f6b2 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 10 Oct 2012 12:03:10 +0200 Subject: [PATCH] wbemprox: Add support for array types. --- dlls/wbemprox/class.c | 18 ++- dlls/wbemprox/query.c | 199 +++++++++++++++++++++++++------ dlls/wbemprox/table.c | 4 +- dlls/wbemprox/wbemprox_private.h | 10 +- 4 files changed, 189 insertions(+), 42 deletions(-) diff --git a/dlls/wbemprox/class.c b/dlls/wbemprox/class.c index 8e1d6642642..b1fc364c473 100644 --- a/dlls/wbemprox/class.c +++ b/dlls/wbemprox/class.c @@ -241,6 +241,11 @@ static void destroy_record( struct record *record ) { if (record->fields[i].type == CIM_STRING || record->fields[i].type == CIM_DATETIME) heap_free( record->fields[i].u.sval ); + else if ((record->fields[i].type & CIM_FLAG_ARRAY) && record->fields[i].u.aval) + { + heap_free( record->fields[i].u.aval->ptr ); + heap_free( record->fields[i].u.aval ); + } } heap_free( record->fields ); heap_free( record ); @@ -327,6 +332,12 @@ static HRESULT record_get_value( const struct record *record, UINT index, VARIAN { if (type) *type = record->fields[index].type; + if (record->fields[index].type & CIM_FLAG_ARRAY) + { + V_VT( var ) = VT_ARRAY; + V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & COL_TYPE_MASK ); + return S_OK; + } switch (record->fields[index].type) { case CIM_STRING: @@ -383,9 +394,14 @@ static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var CIMTYPE type; HRESULT hr; - if ((hr = variant_to_longlong( var, &val, &type )) != S_OK) return hr; + if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr; if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH; + if (type & CIM_FLAG_ARRAY) + { + record->fields[index].u.aval = (struct array *)(INT_PTR)val; + return S_OK; + } switch (type) { case CIM_STRING: diff --git a/dlls/wbemprox/query.c b/dlls/wbemprox/query.c index 8df09bc72c5..f2c1782081d 100644 --- a/dlls/wbemprox/query.c +++ b/dlls/wbemprox/query.c @@ -227,7 +227,7 @@ static HRESULT eval_cond( const struct table *table, UINT row, const struct expr case EXPR_PROPVAL: return eval_propval( table, row, cond->u.propval, val ); case EXPR_SVAL: - *val = (LONGLONG)(INT_PTR)cond->u.sval; + *val = (INT_PTR)cond->u.sval; return S_OK; case EXPR_IVAL: case EXPR_BVAL: @@ -551,50 +551,103 @@ static HRESULT get_system_propval( const struct view *view, UINT index, const WC return WBEM_E_NOT_FOUND; } -static void set_variant( VARTYPE vartype, LONGLONG val, BSTR val_bstr, VARIANT *ret ) +VARTYPE to_vartype( CIMTYPE type ) { - switch (vartype) + switch (type) { - case VT_BOOL: - V_VT( ret ) = VT_BOOL; - V_BOOL( ret ) = val; - return; - case VT_BSTR: - V_VT( ret ) = VT_BSTR; - V_BSTR( ret ) = val_bstr; - return; - case VT_I2: - V_VT( ret ) = VT_I2; - V_I2( ret ) = val; - return; - case VT_UI2: - V_VT( ret ) = VT_UI2; - V_UI2( ret ) = val; - return; - case VT_I4: - V_VT( ret ) = VT_I4; - V_I4( ret ) = val; - return; - case VT_UI4: - V_VT( ret ) = VT_UI4; - V_UI4( ret ) = val; - return; - case VT_NULL: - V_VT( ret ) = VT_NULL; - return; + case CIM_BOOLEAN: return VT_BOOL; + case CIM_STRING: + case CIM_DATETIME: return VT_BSTR; + case CIM_SINT16: return VT_I2; + case CIM_UINT16: return VT_UI2; + case CIM_SINT32: return VT_I4; + case CIM_UINT32: return VT_UI4; + case CIM_SINT64: return VT_I8; + case CIM_UINT64: return VT_UI8; default: - ERR("unhandled variant type %u\n", vartype); + ERR("unhandled type %u\n", type); + break; + } + return 0; +} + +SAFEARRAY *to_safearray( const struct array *array, CIMTYPE type ) +{ + SAFEARRAY *ret; + UINT size = get_type_size( type ); + VARTYPE vartype = to_vartype( type ); + LONG i; + + if (!(ret = SafeArrayCreateVector( vartype, 0, array->count ))) return NULL; + + for (i = 0; i < array->count; i++) + { + void *ptr = (char *)array->ptr + i * size; + if (vartype == VT_BSTR) + { + BSTR str = SysAllocString( *(const WCHAR **)ptr ); + if (!str || SafeArrayPutElement( ret, &i, str ) != S_OK) + { + SysFreeString( str ); + SafeArrayDestroy( ret ); + return NULL; + } + } + else if (SafeArrayPutElement( ret, &i, ptr ) != S_OK) + { + SafeArrayDestroy( ret ); + return NULL; + } + } + return ret; +} + +static void set_variant( VARTYPE type, LONGLONG val, void *val_ptr, VARIANT *ret ) +{ + if (type & VT_ARRAY) + { + V_VT( ret ) = type; + V_ARRAY( ret ) = val_ptr; return; } + switch (type) + { + case VT_BOOL: + V_BOOL( ret ) = val; + break; + case VT_BSTR: + V_BSTR( ret ) = val_ptr; + break; + case VT_I2: + V_I2( ret ) = val; + break; + case VT_UI2: + V_UI2( ret ) = val; + break; + case VT_I4: + V_I4( ret ) = val; + break; + case VT_UI4: + V_UI4( ret ) = val; + break; + case VT_NULL: + break; + default: + ERR("unhandled variant type %u\n", type); + return; + } + V_VT( ret ) = type; } +#define CIM_TYPE_MASK 0xfff + HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VARIANT *ret, CIMTYPE *type, LONG *flavor ) { HRESULT hr; UINT column, row = view->result[index]; VARTYPE vartype; - BSTR val_bstr = NULL; + void *val_ptr = NULL; LONGLONG val; if (is_system_prop( name )) return get_system_propval( view, index, name, ret, type, flavor ); @@ -608,6 +661,14 @@ HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VAR hr = get_value( view->table, row, column, &val ); if (hr != S_OK) return hr; + if (view->table->columns[column].type & CIM_FLAG_ARRAY) + { + CIMTYPE basetype = view->table->columns[column].type & CIM_TYPE_MASK; + + val_ptr = to_safearray( (const struct array *)(INT_PTR)val, basetype ); + if (!vartype) vartype = to_vartype( basetype ) | VT_ARRAY; + goto done; + } switch (view->table->columns[column].type & COL_TYPE_MASK) { case CIM_BOOLEAN: @@ -618,7 +679,7 @@ HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VAR if (val) { vartype = VT_BSTR; - val_bstr = SysAllocString( (const WCHAR *)(INT_PTR)val ); + val_ptr = SysAllocString( (const WCHAR *)(INT_PTR)val ); } else vartype = VT_NULL; @@ -637,29 +698,91 @@ HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VAR break; case CIM_SINT64: vartype = VT_BSTR; - val_bstr = get_value_bstr( view->table, row, column ); + val_ptr = get_value_bstr( view->table, row, column ); break; case CIM_UINT64: vartype = VT_BSTR; - val_bstr = get_value_bstr( view->table, row, column ); + val_ptr = get_value_bstr( view->table, row, column ); break; default: ERR("unhandled column type %u\n", view->table->columns[column].type); return WBEM_E_FAILED; } - set_variant( vartype, val, val_bstr, ret ); + +done: + set_variant( vartype, val, val_ptr, ret ); if (type) *type = view->table->columns[column].type & COL_TYPE_MASK; if (flavor) *flavor = 0; return S_OK; } -HRESULT variant_to_longlong( VARIANT *var, LONGLONG *val, CIMTYPE *type ) +static CIMTYPE to_cimtype( VARTYPE type ) +{ + switch (type) + { + case VT_BOOL: return CIM_BOOLEAN; + case VT_BSTR: return CIM_STRING; + case VT_I2: return CIM_SINT16; + case VT_UI2: return CIM_UINT16; + case VT_I4: return CIM_SINT32; + case VT_UI4: return CIM_UINT32; + case VT_I8: return CIM_SINT64; + case VT_UI8: return CIM_UINT64; + default: + ERR("unhandled type %u\n", type); + break; + } + return 0; +} + +static struct array *to_array( VARIANT *var, CIMTYPE *type ) +{ + struct array *ret; + LONG bound, i; + VARTYPE vartype; + CIMTYPE basetype; + UINT size; + + if (SafeArrayGetVartype( V_ARRAY( var ), &vartype ) != S_OK) return NULL; + if (!(basetype = to_cimtype( vartype ))) return NULL; + if (SafeArrayGetUBound( V_ARRAY( var ), 1, &bound ) != S_OK) return NULL; + if (!(ret = heap_alloc( sizeof(struct array) ))) return NULL; + + ret->count = bound + 1; + size = get_type_size( basetype ); + if (!(ret->ptr = heap_alloc( ret->count * size ))) + { + heap_free( ret ); + return NULL; + } + for (i = 0; i < ret->count; i++) + { + if (SafeArrayGetElement( V_ARRAY( var ), &i, (char *)ret->ptr + i * size ) != S_OK) + { + if (vartype == VT_BSTR) + for (i--; i >= 0; i--) SysFreeString( *(BSTR *)(char *)ret->ptr + i * size ); + heap_free( ret->ptr ); + heap_free( ret ); + return NULL; + } + } + *type = basetype | CIM_FLAG_ARRAY; + return ret; +} + +HRESULT to_longlong( VARIANT *var, LONGLONG *val, CIMTYPE *type ) { if (!var) { *val = 0; return S_OK; } + if (V_VT( var ) & VT_ARRAY) + { + *val = (INT_PTR)to_array( var, type ); + if (!*val) return E_OUTOFMEMORY; + return S_OK; + } switch (V_VT( var )) { case VT_BOOL: @@ -712,7 +835,7 @@ HRESULT put_propval( const struct view *view, UINT index, const WCHAR *name, VAR if (is_method( view->table, column ) || !(view->table->columns[column].type & COL_FLAG_DYNAMIC)) return WBEM_E_FAILED; - hr = variant_to_longlong( var, &val, &type ); + hr = to_longlong( var, &val, &type ); if (hr != S_OK) return hr; return set_value( view->table, row, column, val, type ); diff --git a/dlls/wbemprox/table.c b/dlls/wbemprox/table.c index a49bf585cc2..277998bacd9 100644 --- a/dlls/wbemprox/table.c +++ b/dlls/wbemprox/table.c @@ -99,7 +99,7 @@ HRESULT get_value( const struct table *table, UINT row, UINT column, LONGLONG *v if (table->columns[column].type & CIM_FLAG_ARRAY) { - *val = (LONGLONG)(INT_PTR)*(const void **)ptr; + *val = (INT_PTR)*(const void **)ptr; return S_OK; } switch (table->columns[column].type & COL_TYPE_MASK) @@ -109,7 +109,7 @@ HRESULT get_value( const struct table *table, UINT row, UINT column, LONGLONG *v break; case CIM_DATETIME: case CIM_STRING: - *val = (LONGLONG)(INT_PTR)*(const WCHAR **)ptr; + *val = (INT_PTR)*(const WCHAR **)ptr; break; case CIM_SINT16: *val = *(const INT16 *)ptr; diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h index b0e993335eb..0f1305e3860 100644 --- a/dlls/wbemprox/wbemprox_private.h +++ b/dlls/wbemprox/wbemprox_private.h @@ -67,6 +67,12 @@ struct property const struct property *next; }; +struct array +{ + UINT count; + void *ptr; +}; + struct field { UINT type; @@ -74,6 +80,7 @@ struct field { LONGLONG ival; WCHAR *sval; + struct array *aval; } u; }; @@ -168,7 +175,8 @@ HRESULT get_method( const struct table *, const WCHAR *, class_method ** ) DECLS HRESULT get_propval( const struct view *, UINT, const WCHAR *, VARIANT *, CIMTYPE *, LONG * ) DECLSPEC_HIDDEN; HRESULT put_propval( const struct view *, UINT, const WCHAR *, VARIANT *, CIMTYPE ) DECLSPEC_HIDDEN; -HRESULT variant_to_longlong( VARIANT *, LONGLONG *, CIMTYPE * ) DECLSPEC_HIDDEN; +HRESULT to_longlong( VARIANT *, LONGLONG *, CIMTYPE * ) DECLSPEC_HIDDEN; +SAFEARRAY *to_safearray( const struct array *, CIMTYPE ) DECLSPEC_HIDDEN; HRESULT get_properties( const struct view *, SAFEARRAY ** ) DECLSPEC_HIDDEN; HRESULT get_object( const WCHAR *, IWbemClassObject ** ) DECLSPEC_HIDDEN; BSTR get_method_name( const WCHAR *, UINT ) DECLSPEC_HIDDEN;