[5/5] wbemprox: Add support for array types.

Hans Leidekker hans at codeweavers.com
Wed Oct 10 05:03:10 CDT 2012


---
 dlls/wbemprox/class.c            |   18 +++-
 dlls/wbemprox/query.c            |  175 ++++++++++++++++++++++++++++++++------
 dlls/wbemprox/table.c            |    4 +-
 dlls/wbemprox/wbemprox_private.h |   10 ++-
 4 files changed, 177 insertions(+), 30 deletions(-)

diff --git a/dlls/wbemprox/class.c b/dlls/wbemprox/class.c
index 8e1d664..b1fc364 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 8df09bc..c5de46f 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 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 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_VT( ret ) = VT_BOOL;
         V_BOOL( ret ) = val;
-        return;
+        break;
     case VT_BSTR:
-        V_VT( ret ) = VT_BSTR;
-        V_BSTR( ret ) = val_bstr;
-        return;
+        V_BSTR( ret ) = val_ptr;
+        break;
     case VT_I2:
-        V_VT( ret ) = VT_I2;
         V_I2( ret ) = val;
-        return;
+        break;
     case VT_UI2:
-        V_VT( ret ) = VT_UI2;
         V_UI2( ret ) = val;
-        return;
+        break;
     case VT_I4:
-        V_VT( ret ) = VT_I4;
         V_I4( ret ) = val;
-        return;
+        break;
     case VT_UI4:
-        V_VT( ret ) = VT_UI4;
         V_UI4( ret ) = val;
-        return;
+        break;
     case VT_NULL:
-        V_VT( ret ) = VT_NULL;
-        return;
+        break;
     default:
-        ERR("unhandled variant type %u\n", vartype);
+        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 a49bf58..277998b 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 b0e9933..0f1305e 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;
-- 
1.7.10.4






More information about the wine-patches mailing list