diff --git a/dlls/wbemprox/class.c b/dlls/wbemprox/class.c index af7d8f5fc60..293c8c4e0f6 100644 --- a/dlls/wbemprox/class.c +++ b/dlls/wbemprox/class.c @@ -441,6 +441,163 @@ static HRESULT WINAPI class_object_InheritsFrom( return E_NOTIMPL; } +static UINT count_instances( IEnumWbemClassObject *iter ) +{ + UINT count = 0; + while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++; + IEnumWbemClassObject_Reset( iter ); + return count; +} + +static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr ) +{ + switch (type) + { + case CIM_SINT16: + *(INT16 *)ptr = val; + break; + case CIM_UINT16: + *(UINT16 *)ptr = val; + break; + case CIM_SINT32: + *(INT32 *)ptr = val; + break; + case CIM_UINT32: + *(UINT32 *)ptr = val; + break; + default: + FIXME("unhandled type %u\n", type); + break; + } +} + +HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols, + struct column **cols, BYTE **data ) +{ + static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0}; + static const WCHAR typeW[] = {'T','y','p','e',0}; + static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0}; + struct column *columns; + BYTE *row; + IWbemClassObject *param; + VARIANT val; + HRESULT hr = E_OUTOFMEMORY; + UINT offset = 0; + ULONG count; + int i = 0; + + count = count_instances( iter ); + if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY; + if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error; + + for (;;) + { + IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, ¶m, &count ); + if (!count) break; + + hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL ); + if (hr != S_OK) goto error; + columns[i].name = heap_strdupW( V_BSTR( &val ) ); + VariantClear( &val ); + + hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL ); + if (hr != S_OK) goto error; + columns[i].type = V_UI4( &val ); + columns[i].vartype = 0; + + hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL ); + if (hr != S_OK) goto error; + if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset ); + offset += get_type_size( columns[i].type ); + + IWbemClassObject_Release( param ); + i++; + } + *num_cols = i; + *cols = columns; + *data = row; + return S_OK; + +error: + for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name ); + heap_free( columns ); + heap_free( row ); + return hr; +} + +HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name ) +{ + HRESULT hr; + struct table *table; + struct column *columns; + UINT num_cols; + BYTE *row; + + hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row ); + if (hr != S_OK) return hr; + + if (!(table = create_table( name, num_cols, columns, 1, row, NULL ))) + { + free_columns( columns, num_cols ); + heap_free( row ); + return E_OUTOFMEMORY; + } + if (!add_table( table )) free_table( table ); /* already exists */ + return S_OK; +} + +WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir ) +{ + static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0}; + static const WCHAR outW[] = {'O','U','T',0}; + static const WCHAR inW[] = {'I','N',0}; + UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method ); + WCHAR *ret; + + if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL; + sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW ); + return struprW( ret ); +} + +static HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir, + IWbemClassObject **sig ) +{ + static const WCHAR selectW[] = + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', + '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ', + 'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ', + 'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ', + 'D','i','r','e','c','t','i','o','n','%','s',0}; + static const WCHAR geW[] = {'>','=','0',0}; + static const WCHAR leW[] = {'<','=','0',0}; + UINT len = SIZEOF(selectW) + SIZEOF(geW); + IEnumWbemClassObject *iter; + WCHAR *query, *name; + HRESULT hr; + + len += strlenW( class ) + strlenW( method ); + if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY; + sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW ); + + hr = exec_query( query, &iter ); + heap_free( query ); + if (hr != S_OK) return hr; + + if (!(name = build_signature_table_name( class, method, dir ))) + { + IEnumWbemClassObject_Release( iter ); + return E_OUTOFMEMORY; + } + hr = create_signature_table( iter, name ); + IEnumWbemClassObject_Release( iter ); + if (hr != S_OK) + { + heap_free( name ); + return hr; + } + return get_object( name, sig ); +} + static HRESULT WINAPI class_object_GetMethod( IWbemClassObject *iface, LPCWSTR wszName, @@ -448,8 +605,19 @@ static HRESULT WINAPI class_object_GetMethod( IWbemClassObject **ppInSignature, IWbemClassObject **ppOutSignature ) { - FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature); - return E_NOTIMPL; + struct class_object *co = impl_from_IWbemClassObject( iface ); + struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter ); + struct view *view = ec->query->view; + HRESULT hr; + + TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature); + + hr = create_signature( view->table->name, wszName, PARAM_IN, ppInSignature ); + if (hr != S_OK) return hr; + + hr = create_signature( view->table->name, wszName, PARAM_OUT, ppOutSignature ); + if (hr != S_OK) IWbemClassObject_Release( *ppInSignature ); + return hr; } static HRESULT WINAPI class_object_PutMethod( diff --git a/dlls/wbemprox/table.c b/dlls/wbemprox/table.c index d3ad06ddb9a..d94a8e8fb3b 100644 --- a/dlls/wbemprox/table.c +++ b/dlls/wbemprox/table.c @@ -44,11 +44,11 @@ HRESULT get_column_index( const struct table *table, const WCHAR *name, UINT *co return WBEM_E_INVALID_QUERY; } -static UINT get_column_size( const struct table *table, UINT column ) +UINT get_type_size( CIMTYPE type ) { - if (table->columns[column].type & CIM_FLAG_ARRAY) return sizeof(void *); + if (type & CIM_FLAG_ARRAY) return sizeof(void *); - switch (table->columns[column].type & COL_TYPE_MASK) + switch (type) { case CIM_SINT16: case CIM_UINT16: @@ -63,10 +63,15 @@ static UINT get_column_size( const struct table *table, UINT column ) case CIM_STRING: return sizeof(WCHAR *); default: - ERR("unknown column type %u\n", table->columns[column].type & COL_TYPE_MASK); + ERR("unhandled type %u\n", type); break; } - return sizeof(INT32); + return sizeof(LONGLONG); +} + +static UINT get_column_size( const struct table *table, UINT column ) +{ + return get_type_size( table->columns[column].type & COL_TYPE_MASK ); } static UINT get_column_offset( const struct table *table, UINT column ) diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h index 725ea8cbdd5..a5f0a42beee 100644 --- a/dlls/wbemprox/wbemprox_private.h +++ b/dlls/wbemprox/wbemprox_private.h @@ -24,6 +24,13 @@ struct list *table_list; #define SIZEOF(array) (sizeof(array)/sizeof((array)[0])) +enum param_direction +{ + PARAM_OUT = -1, + PARAM_INOUT = 0, + PARAM_IN = 1 +}; + #define COL_TYPE_MASK 0x0000ffff #define COL_FLAG_DYNAMIC 0x00010000 #define COL_FLAG_KEY 0x00020000 @@ -134,6 +141,7 @@ struct table *create_table( const WCHAR *, UINT, const struct column *, UINT, BOOL add_table( struct table * ) DECLSPEC_HIDDEN; void free_columns( struct column *, UINT ) DECLSPEC_HIDDEN; void free_table( struct table * ) DECLSPEC_HIDDEN; +UINT get_type_size( CIMTYPE ) 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; @@ -161,6 +169,12 @@ static inline void *heap_realloc( void *mem, size_t len ) return HeapReAlloc( GetProcessHeap(), 0, mem, len ); } +static void *heap_alloc_zero( size_t len ) __WINE_ALLOC_SIZE(1); +static inline void *heap_alloc_zero( size_t len ) +{ + return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ); +} + static inline BOOL heap_free( void *mem ) { return HeapFree( GetProcessHeap(), 0, mem );