wbemprox: Add support for evaluating ASSOCIATORS OF queries.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2019-09-10 17:09:14 +02:00 committed by Alexandre Julliard
parent c69813bcd0
commit 8487265f81
6 changed files with 496 additions and 156 deletions

View File

@ -50,6 +50,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
static const WCHAR class_associatorsW[] =
{'_','_','A','S','S','O','C','I','A','T','O','R','S',0};
static const WCHAR class_baseboardW[] =
{'W','i','n','3','2','_','B','a','s','e','B','o','a','r','d',0};
static const WCHAR class_biosW[] =
@ -137,6 +139,10 @@ static const WCHAR prop_antecedentW[] =
{'A','n','t','e','c','e','d','e','n','t',0};
static const WCHAR prop_architectureW[] =
{'A','r','c','h','i','t','e','c','t','u','r','e',0};
static const WCHAR prop_assocclassW[] =
{'A','s','s','o','c','C','l','a','s','s',0};
static const WCHAR prop_associatorW[] =
{'A','s','s','o','c','i','a','t','o','r',0};
static const WCHAR prop_attributesW[] =
{'A','t','t','r','i','b','u','t','e','s',0};
static const WCHAR prop_availabilityW[] =
@ -433,6 +439,12 @@ static const WCHAR prop_workingsetsizeW[] =
{'W','o','r','k','i','n','g','S','e','t','S','i','z','e',0};
/* column definitions must be kept in sync with record structures below */
static const struct column col_associator[] =
{
{ prop_assocclassW, CIM_STRING },
{ prop_classW, CIM_STRING },
{ prop_associatorW, CIM_STRING }
};
static const struct column col_baseboard[] =
{
{ prop_manufacturerW, CIM_STRING|COL_FLAG_DYNAMIC },
@ -871,6 +883,12 @@ static const WCHAR videocontroller_statusW[] =
{'O','K',0};
#include "pshpack1.h"
struct record_associator
{
const WCHAR *assocclass;
const WCHAR *class;
const WCHAR *associator;
};
struct record_baseboard
{
const WCHAR *manufacturer;
@ -1214,6 +1232,11 @@ struct record_videocontroller
};
#include "poppack.h"
static const struct record_associator data_associator[] =
{
{ class_diskdrivetodiskpartitionW, class_diskpartitionW, class_diskdriveW },
{ class_logicaldisktopartitionW, class_logicaldiskW, class_diskpartitionW },
};
static const struct record_param data_param[] =
{
{ class_processW, method_getownerW, -1, param_returnvalueW, CIM_UINT32, VT_I4 },
@ -2489,9 +2512,9 @@ static struct association *get_diskdrivetodiskpartition_pairs( UINT *count )
if ((hr = parse_query( select2W, &query2->view, &query2->mem )) != S_OK) goto done;
if ((hr = execute_view( query2->view )) != S_OK) goto done;
if (!(ret = heap_alloc_zero( query->view->count * sizeof(*ret) ))) goto done;
if (!(ret = heap_alloc_zero( query->view->result_count * sizeof(*ret) ))) goto done;
for (i = 0; i < query->view->count; i++)
for (i = 0; i < query->view->result_count; i++)
{
if ((hr = get_propval( query->view, i, pathW, &val, NULL, NULL )) != S_OK) goto done;
if (!(ret[i].ref = heap_strdupW( V_BSTR(&val) ))) goto done;
@ -2502,10 +2525,10 @@ static struct association *get_diskdrivetodiskpartition_pairs( UINT *count )
VariantClear( &val );
}
*count = query->view->count;
*count = query->view->result_count;
done:
if (!ret) free_assocations( ret, query->view->count );
if (!ret) free_assocations( ret, query->view->result_count );
free_query( query );
free_query( query2 );
return ret;
@ -2754,10 +2777,10 @@ static struct association *get_logicaldisktopartition_pairs( UINT *count )
if ((hr = parse_query( select2W, &query2->view, &query2->mem )) != S_OK) goto done;
if ((hr = execute_view( query2->view )) != S_OK) goto done;
if (!(ret = heap_alloc_zero( query->view->count * sizeof(*ret) ))) goto done;
if (!(ret = heap_alloc_zero( query->view->result_count * sizeof(*ret) ))) goto done;
/* assume fixed and removable disks are enumerated in the same order as partitions */
for (i = 0; i < query->view->count; i++)
for (i = 0; i < query->view->result_count; i++)
{
if ((hr = get_propval( query->view, i, pathW, &val, NULL, NULL )) != S_OK) goto done;
if (!(ret[i].ref = heap_strdupW( V_BSTR(&val) ))) goto done;
@ -2768,10 +2791,10 @@ static struct association *get_logicaldisktopartition_pairs( UINT *count )
VariantClear( &val );
}
*count = query->view->count;
*count = query->view->result_count;
done:
if (!ret) free_assocations( ret, query->view->count );
if (!ret) free_assocations( ret, query->view->result_count );
free_query( query );
free_query( query2 );
return ret;
@ -4266,6 +4289,7 @@ done:
#define D(d) sizeof(d)/sizeof(d[0]), 0, (BYTE *)d
static struct table builtin_classes[] =
{
{ class_associatorsW, C(col_associator), D(data_associator) },
{ class_baseboardW, C(col_baseboard), 0, 0, NULL, fill_baseboard },
{ class_biosW, C(col_bios), 0, 0, NULL, fill_bios },
{ class_cdromdriveW, C(col_cdromdrive), 0, 0, NULL, fill_cdromdrive },

View File

@ -113,6 +113,7 @@ static HRESULT WINAPI enum_class_object_Next(
{
struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
struct view *view = ec->query->view;
struct table *table;
static int once = 0;
HRESULT hr;
@ -123,14 +124,15 @@ static HRESULT WINAPI enum_class_object_Next(
if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
*puReturned = 0;
if (ec->index >= view->count) return WBEM_S_FALSE;
if (ec->index >= view->result_count) return WBEM_S_FALSE;
hr = create_class_object( view->table->name, iface, ec->index, NULL, apObjects );
table = get_view_table( view, ec->index );
hr = create_class_object( table->name, iface, ec->index, NULL, apObjects );
if (hr != S_OK) return hr;
ec->index++;
*puReturned = 1;
if (ec->index == view->count && uCount > 1) return WBEM_S_FALSE;
if (ec->index == view->result_count && uCount > 1) return WBEM_S_FALSE;
if (uCount > 1) return WBEM_S_TIMEDOUT;
return WBEM_S_NO_ERROR;
}
@ -168,11 +170,11 @@ static HRESULT WINAPI enum_class_object_Skip(
if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
if (!view->count) return WBEM_S_FALSE;
if (!view->result_count) return WBEM_S_FALSE;
if (nCount > view->count - ec->index)
if (nCount > view->result_count - ec->index)
{
ec->index = view->count - 1;
ec->index = view->result_count - 1;
return WBEM_S_FALSE;
}
ec->index += nCount;
@ -491,7 +493,7 @@ static HRESULT WINAPI class_object_GetNames(
if (wszQualifierName || pQualifierVal)
FIXME("qualifier not supported\n");
return get_properties( ec->query->view, lFlags, pNames );
return get_properties( ec->query->view, co->index, lFlags, pNames );
}
static HRESULT WINAPI class_object_BeginEnumeration(
@ -519,17 +521,18 @@ static HRESULT WINAPI class_object_Next(
struct class_object *obj = impl_from_IWbemClassObject( iface );
struct enum_class_object *iter = impl_from_IEnumWbemClassObject( obj->iter );
struct view *view = iter->query->view;
struct table *table = get_view_table( view, obj->index );
BSTR prop;
HRESULT hr;
UINT i;
TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
for (i = obj->index_property; i < view->table->num_cols; i++)
for (i = obj->index_property; i < table->num_cols; i++)
{
if (is_method( view->table, i )) continue;
if (!is_selected_prop( view, view->table->columns[i].name )) continue;
if (!(prop = SysAllocString( view->table->columns[i].name ))) return E_OUTOFMEMORY;
if (is_method( table, i )) continue;
if (!is_result_prop( view, table->columns[i].name )) continue;
if (!(prop = SysAllocString( table->columns[i].name ))) return E_OUTOFMEMORY;
if ((hr = get_propval( view, obj->index, prop, pVal, pType, plFlavor )) != S_OK)
{
SysFreeString( prop );
@ -612,15 +615,16 @@ static BSTR get_object_text( const struct view *view, UINT index )
static const WCHAR fmtW[] =
{'\n','i','n','s','t','a','n','c','e',' ','o','f',' ','%','s','\n','{','%','s','\n','}',';',0};
UINT len, len_body, row = view->result[index];
struct table *table = get_view_table( view, index );
BSTR ret, body;
len = ARRAY_SIZE( fmtW );
len += lstrlenW( view->table->name );
if (!(body = get_body_text( view->table, row, &len_body ))) return NULL;
len += lstrlenW( table->name );
if (!(body = get_body_text( table, row, &len_body ))) return NULL;
len += len_body;
if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
swprintf( ret, len, fmtW, view->table->name, body );
swprintf( ret, len, fmtW, table->name, body );
SysFreeString( body );
return ret;
}
@ -660,12 +664,12 @@ static HRESULT WINAPI class_object_SpawnInstance(
{
struct class_object *co = impl_from_IWbemClassObject( iface );
struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
struct view *view = ec->query->view;
struct table *table = get_view_table( ec->query->view, co->index );
struct record *record;
TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
if (!(record = create_record( view->table ))) return E_OUTOFMEMORY;
if (!(record = create_record( table ))) return E_OUTOFMEMORY;
return create_class_object( co->name, NULL, 0, record, ppNewInstance );
}

View File

@ -29,25 +29,56 @@
WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
HRESULT create_view( const WCHAR *path, const struct keyword *keywordlist, const WCHAR *class,
static HRESULT append_table( struct view *view, struct table *table )
{
struct table **tmp;
if (!(tmp = heap_realloc( view->table, (view->table_count + 1) * sizeof(*tmp) ))) return E_OUTOFMEMORY;
view->table = tmp;
view->table[view->table_count++] = table;
return S_OK;
}
HRESULT create_view( enum view_type type, const WCHAR *path, const struct keyword *keywordlist, const WCHAR *class,
const struct property *proplist, const struct expr *cond, struct view **ret )
{
struct view *view = heap_alloc_zero( sizeof(*view) );
if (!view) return E_OUTOFMEMORY;
view->path = path;
view->keywordlist = keywordlist;
view->proplist = proplist;
view->table = grab_table( class );
view->cond = cond;
switch (type)
{
case VIEW_TYPE_ASSOCIATORS:
view->path = path;
view->keywordlist = keywordlist;
break;
case VIEW_TYPE_SELECT:
{
struct table *table = grab_table( class );
HRESULT hr;
if (table && (hr = append_table( view, table )) != S_OK) return hr;
view->proplist = proplist;
view->cond = cond;
break;
}
default:
ERR( "unhandled type %u\n", type );
heap_free( view );
return E_INVALIDARG;
}
view->type = type;
*ret = view;
return S_OK;
}
void destroy_view( struct view *view )
{
ULONG i;
if (!view) return;
if (view->table) release_table( view->table );
for (i = 0; i < view->table_count; i++) release_table( view->table[i] );
heap_free( view->table );
heap_free( view->result );
heap_free( view );
}
@ -440,24 +471,242 @@ HRESULT eval_cond( const struct table *table, UINT row, const struct expr *cond,
return WBEM_E_INVALID_QUERY;
}
HRESULT execute_view( struct view *view )
static WCHAR *build_assoc_query( const WCHAR *class, UINT class_len )
{
static const WCHAR fmtW[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','_','_','A','S','S','O','C','I','A','T','O','R','S',
' ','W','H','E','R','E',' ','C','l','a','s','s','=','\'','%','s','\'',0};
UINT len = class_len + ARRAY_SIZE(fmtW);
WCHAR *ret;
if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
swprintf( ret, len, fmtW, class );
return ret;
}
static HRESULT create_assoc_enum( const WCHAR *class, UINT class_len, IEnumWbemClassObject **iter )
{
WCHAR *query;
HRESULT hr;
if (!(query = build_assoc_query( class, class_len ))) return E_OUTOFMEMORY;
hr = exec_query( query, iter );
heap_free( query );
return hr;
}
static WCHAR *build_antecedent_query( const WCHAR *assocclass, const WCHAR *dependent )
{
static const WCHAR fmtW[] =
{'S','E','L','E','C','T',' ','A','n','t','e','c','e','d','e','n','t',' ','F','R','O','M',' ','%','s',' ',
'W','H','E','R','E',' ','D','e','p','e','n','d','e','n','t','=','\'','%','s','\'',0};
UINT len = lstrlenW(assocclass) + lstrlenW(dependent) + ARRAY_SIZE(fmtW);
WCHAR *ret;
if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
swprintf( ret, len, fmtW, assocclass, dependent );
return ret;
}
static BSTR build_servername(void)
{
WCHAR server[MAX_COMPUTERNAME_LENGTH + 1], *p;
DWORD len = ARRAY_SIZE( server );
if (!(GetComputerNameW( server, &len ))) return NULL;
for (p = server; *p; p++) *p = towupper( *p );
return SysAllocString( server );
}
static BSTR build_namespace(void)
{
static const WCHAR cimv2W[] = {'R','O','O','T','\\','C','I','M','V','2',0};
return SysAllocString( cimv2W );
}
static WCHAR *build_canonical_path( const WCHAR *relpath )
{
static const WCHAR fmtW[] = {'\\','\\','%','s','\\','%','s',':',0};
BSTR server, namespace;
WCHAR *ret;
UINT len, i;
if (!(server = build_servername())) return NULL;
if (!(namespace = build_namespace()))
{
SysFreeString( server );
return NULL;
}
len = ARRAY_SIZE( fmtW ) + SysStringLen( server ) + SysStringLen( namespace ) + lstrlenW( relpath );
if ((ret = heap_alloc( len * sizeof(WCHAR ) )))
{
len = swprintf( ret, len, fmtW, server, namespace );
for (i = 0; i < lstrlenW( relpath ); i ++)
{
if (relpath[i] == '\'') ret[len++] = '"';
else ret[len++] = relpath[i];
}
ret[len] = 0;
}
SysFreeString( server );
SysFreeString( namespace );
return ret;
}
static HRESULT get_antecedent( const WCHAR *assocclass, const WCHAR *dependent, BSTR *ret )
{
static const WCHAR antecedentW[] = {'A','n','t','e','c','e','d','e','n','t',0};
WCHAR *fullpath, *str;
IEnumWbemClassObject *iter = NULL;
IWbemClassObject *obj;
HRESULT hr = E_OUTOFMEMORY;
ULONG count;
VARIANT var;
if (!(fullpath = build_canonical_path( dependent ))) return E_OUTOFMEMORY;
if (!(str = build_antecedent_query( assocclass, fullpath ))) goto done;
if ((hr = exec_query( str, &iter )) != S_OK) goto done;
IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &obj, &count );
if (!count)
{
*ret = NULL;
goto done;
}
hr = IWbemClassObject_Get( obj, antecedentW, 0, &var, NULL, NULL );
IWbemClassObject_Release( obj );
if (hr != S_OK) goto done;
*ret = V_BSTR( &var );
done:
if (iter) IEnumWbemClassObject_Release( iter );
heap_free( str );
heap_free( fullpath );
return hr;
}
static HRESULT do_query( const WCHAR *str, struct query **ret_query )
{
struct query *query;
HRESULT hr;
if (!(query = create_query())) return E_OUTOFMEMORY;
if ((hr = parse_query( str, &query->view, &query->mem )) != S_OK || (hr = execute_view( query->view )) != S_OK)
{
release_query( query );
return hr;
}
*ret_query = query;
return S_OK;
}
static HRESULT get_antecedent_table( const WCHAR *assocclass, const WCHAR *dependent, struct table **table )
{
BSTR antecedent = NULL;
struct path *path = NULL;
WCHAR *str = NULL;
struct query *query = NULL;
HRESULT hr;
if ((hr = get_antecedent( assocclass, dependent, &antecedent )) != S_OK) return hr;
if (!antecedent)
{
*table = NULL;
return S_OK;
}
if ((hr = parse_path( antecedent, &path )) != S_OK) goto done;
if (!(str = query_from_path( path )))
{
hr = E_OUTOFMEMORY;
goto done;
}
if ((hr = do_query( str, &query )) != S_OK) goto done;
if (query->view->table_count) *table = addref_table( query->view->table[0] );
else *table = NULL;
done:
if (query) release_query( query );
free_path( path );
SysFreeString( antecedent );
return hr;
}
static HRESULT exec_assoc_view( struct view *view )
{
static const WCHAR assocclassW[] = {'A','s','s','o','c','C','l','a','s','s',0};
IEnumWbemClassObject *iter = NULL;
struct path *path;
HRESULT hr;
if (view->keywordlist) FIXME( "ignoring keywords\n" );
if ((hr = parse_path( view->path, &path )) != S_OK) return hr;
if ((hr = create_assoc_enum( path->class, path->class_len, &iter )) != S_OK) goto done;
for (;;)
{
ULONG count;
IWbemClassObject *obj;
struct table *table;
VARIANT var;
IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &obj, &count );
if (!count) break;
if ((hr = IWbemClassObject_Get( obj, assocclassW, 0, &var, NULL, NULL )) != S_OK)
{
IWbemClassObject_Release( obj );
goto done;
}
IWbemClassObject_Release( obj );
hr = get_antecedent_table( V_BSTR(&var), view->path, &table );
VariantClear( &var );
if (hr != S_OK) goto done;
if (table && (hr = append_table( view, table )) != S_OK)
{
release_table( table );
goto done;
}
}
if (view->table_count)
{
if (!(view->result = heap_alloc_zero( view->table_count * sizeof(UINT) ))) hr = E_OUTOFMEMORY;
else view->result_count = view->table_count;
}
done:
if (iter) IEnumWbemClassObject_Release( iter );
free_path( path );
return hr;
}
static HRESULT exec_select_view( struct view *view )
{
UINT i, j = 0, len;
enum fill_status status = FILL_STATUS_UNFILTERED;
struct table *table;
if (!view->table) return S_OK;
if (view->table->fill)
if (!view->table_count) return S_OK;
table = view->table[0];
if (table->fill)
{
clear_table( view->table );
status = view->table->fill( view->table, view->cond );
clear_table( table );
status = table->fill( table, view->cond );
}
if (status == FILL_STATUS_FAILED) return WBEM_E_FAILED;
if (!view->table->num_rows) return S_OK;
if (!table->num_rows) return S_OK;
len = min( view->table->num_rows, 16 );
len = min( table->num_rows, 16 );
if (!(view->result = heap_alloc( len * sizeof(UINT) ))) return E_OUTOFMEMORY;
for (i = 0; i < view->table->num_rows; i++)
for (i = 0; i < table->num_rows; i++)
{
HRESULT hr;
LONGLONG val = 0;
@ -471,13 +720,30 @@ HRESULT execute_view( struct view *view )
view->result = tmp;
}
if (status == FILL_STATUS_FILTERED) val = 1;
else if ((hr = eval_cond( view->table, i, view->cond, &val, &type )) != S_OK) return hr;
else if ((hr = eval_cond( table, i, view->cond, &val, &type )) != S_OK) return hr;
if (val) view->result[j++] = i;
}
view->count = j;
view->result_count = j;
return S_OK;
}
HRESULT execute_view( struct view *view )
{
switch (view->type)
{
case VIEW_TYPE_ASSOCIATORS:
return exec_assoc_view( view );
case VIEW_TYPE_SELECT:
return exec_select_view( view );
default:
ERR( "unhandled type %u\n", view->type );
return E_INVALIDARG;
}
}
struct query *create_query(void)
{
struct query *query;
@ -527,10 +793,9 @@ done:
return hr;
}
BOOL is_selected_prop( const struct view *view, const WCHAR *name )
BOOL is_result_prop( const struct view *view, const WCHAR *name )
{
const struct property *prop = view->proplist;
if (!prop) return TRUE;
while (prop)
{
@ -545,47 +810,21 @@ static BOOL is_system_prop( const WCHAR *name )
return (name[0] == '_' && name[1] == '_');
}
static BSTR build_servername( const struct view *view )
{
WCHAR server[MAX_COMPUTERNAME_LENGTH + 1], *p;
DWORD len = ARRAY_SIZE( server );
if (view->proplist) return NULL;
if (!(GetComputerNameW( server, &len ))) return NULL;
for (p = server; *p; p++) *p = towupper( *p );
return SysAllocString( server );
}
static BSTR build_classname( const struct view *view )
{
return SysAllocString( view->table->name );
}
static BSTR build_namespace( const struct view *view )
{
static const WCHAR cimv2W[] = {'R','O','O','T','\\','C','I','M','V','2',0};
if (view->proplist) return NULL;
return SysAllocString( cimv2W );
}
static BSTR build_proplist( const struct view *view, UINT index, UINT count, UINT *len )
static BSTR build_proplist( const struct table *table, UINT row, UINT count, UINT *len )
{
static const WCHAR fmtW[] = {'%','s','=','%','s',0};
UINT i, j, offset, row = view->result[index];
UINT i, j, offset;
BSTR *values, ret = NULL;
if (!(values = heap_alloc( count * sizeof(BSTR) ))) return NULL;
*len = j = 0;
for (i = 0; i < view->table->num_cols; i++)
for (i = 0; i < table->num_cols; i++)
{
if (view->table->columns[i].type & COL_FLAG_KEY)
if (table->columns[i].type & COL_FLAG_KEY)
{
const WCHAR *name = view->table->columns[i].name;
values[j] = get_value_bstr( view->table, row, i );
const WCHAR *name = table->columns[i].name;
values[j] = get_value_bstr( table, row, i );
*len += lstrlenW( fmtW ) + lstrlenW( name ) + lstrlenW( values[j] );
j++;
}
@ -593,12 +832,11 @@ static BSTR build_proplist( const struct view *view, UINT index, UINT count, UIN
if ((ret = SysAllocStringLen( NULL, *len )))
{
offset = j = 0;
for (i = 0; i < view->table->num_cols; i++)
for (i = 0; i < table->num_cols; i++)
{
if (view->table->columns[i].type & COL_FLAG_KEY)
if (table->columns[i].type & COL_FLAG_KEY)
{
const WCHAR *name = view->table->columns[i].name;
const WCHAR *name = table->columns[i].name;
offset += swprintf( ret + offset, *len - offset, fmtW, name, values[j] );
if (j < count - 1) ret[offset++] = ',';
j++;
@ -610,28 +848,30 @@ static BSTR build_proplist( const struct view *view, UINT index, UINT count, UIN
return ret;
}
static UINT count_key_columns( const struct view *view )
static UINT count_key_columns( const struct table *table )
{
UINT i, num_keys = 0;
for (i = 0; i < view->table->num_cols; i++)
for (i = 0; i < table->num_cols; i++)
{
if (view->table->columns[i].type & COL_FLAG_KEY) num_keys++;
if (table->columns[i].type & COL_FLAG_KEY) num_keys++;
}
return num_keys;
}
static BSTR build_relpath( const struct view *view, UINT index, const WCHAR *name )
static BSTR build_relpath( const struct view *view, UINT table_index, UINT result_index, const WCHAR *name )
{
static const WCHAR fmtW[] = {'%','s','.','%','s',0};
BSTR class, proplist, ret = NULL;
struct table *table = view->table[table_index];
UINT row = view->result[result_index];
UINT num_keys, len;
if (view->proplist) return NULL;
if (!(class = build_classname( view ))) return NULL;
if (!(num_keys = count_key_columns( view ))) return class;
if (!(proplist = build_proplist( view, index, num_keys, &len ))) goto done;
if (!(class = SysAllocString( view->table[table_index]->name ))) return NULL;
if (!(num_keys = count_key_columns( table ))) return class;
if (!(proplist = build_proplist( table, row, num_keys, &len ))) goto done;
len += lstrlenW( fmtW ) + SysStringLen( class );
if (!(ret = SysAllocStringLen( NULL, len ))) goto done;
@ -643,7 +883,7 @@ done:
return ret;
}
static BSTR build_path( const struct view *view, UINT index, const WCHAR *name )
static BSTR build_path( const struct view *view, UINT table_index, UINT result_index, const WCHAR *name )
{
static const WCHAR fmtW[] = {'\\','\\','%','s','\\','%','s',':','%','s',0};
BSTR server, namespace = NULL, relpath = NULL, ret = NULL;
@ -651,9 +891,9 @@ static BSTR build_path( const struct view *view, UINT index, const WCHAR *name )
if (view->proplist) return NULL;
if (!(server = build_servername( view ))) return NULL;
if (!(namespace = build_namespace( view ))) goto done;
if (!(relpath = build_relpath( view, index, name ))) goto done;
if (!(server = build_servername())) return NULL;
if (!(namespace = build_namespace())) goto done;
if (!(relpath = build_relpath( view, table_index, result_index, name ))) goto done;
len = lstrlenW( fmtW ) + SysStringLen( server ) + SysStringLen( namespace ) + SysStringLen( relpath );
if (!(ret = SysAllocStringLen( NULL, len ))) goto done;
@ -671,30 +911,30 @@ BOOL is_method( const struct table *table, UINT column )
return table->columns[column].type & COL_FLAG_METHOD;
}
static UINT count_properties( const struct view *view )
static UINT count_properties( const struct table *table )
{
UINT i, num_props = 0;
for (i = 0; i < view->table->num_cols; i++)
for (i = 0; i < table->num_cols; i++)
{
if (!is_method( view->table, i)) num_props++;
if (!is_method( table, i )) num_props++;
}
return num_props;
}
static UINT count_selected_properties( const struct view *view )
static UINT count_result_properties( const struct view *view, UINT table_index )
{
const struct property *prop = view->proplist;
UINT count;
if (!prop) return count_properties( view );
if (!prop) return count_properties( view->table[table_index] );
count = 1;
while ((prop = prop->next)) count++;
return count;
}
static HRESULT get_system_propval( const struct view *view, UINT index, const WCHAR *name,
static HRESULT get_system_propval( const struct view *view, UINT table_index, UINT result_index, const WCHAR *name,
VARIANT *ret, CIMTYPE *type, LONG *flavor )
{
static const WCHAR classW[] = {'_','_','C','L','A','S','S',0};
@ -712,7 +952,7 @@ static HRESULT get_system_propval( const struct view *view, UINT index, const WC
if (ret)
{
V_VT( ret ) = VT_BSTR;
V_BSTR( ret ) = build_classname( view );
V_BSTR( ret ) = SysAllocString( view->table[table_index]->name );
}
if (type) *type = CIM_STRING;
return S_OK;
@ -732,7 +972,7 @@ static HRESULT get_system_propval( const struct view *view, UINT index, const WC
if (ret)
{
V_VT( ret ) = VT_BSTR;
V_BSTR( ret ) = build_namespace( view );
V_BSTR( ret ) = view->proplist ? NULL : build_namespace();
}
if (type) *type = CIM_STRING;
return S_OK;
@ -742,7 +982,7 @@ static HRESULT get_system_propval( const struct view *view, UINT index, const WC
if (ret)
{
V_VT( ret ) = VT_BSTR;
V_BSTR( ret ) = build_path( view, index, name );
V_BSTR( ret ) = build_path( view, table_index, result_index, name );
}
if (type) *type = CIM_STRING;
return S_OK;
@ -752,7 +992,7 @@ static HRESULT get_system_propval( const struct view *view, UINT index, const WC
if (ret)
{
V_VT( ret ) = VT_I4;
V_I4( ret ) = count_selected_properties( view );
V_I4( ret ) = count_result_properties( view, table_index );
}
if (type) *type = CIM_SINT32;
return S_OK;
@ -762,7 +1002,7 @@ static HRESULT get_system_propval( const struct view *view, UINT index, const WC
if (ret)
{
V_VT( ret ) = VT_BSTR;
V_BSTR( ret ) = build_relpath( view, index, name );
V_BSTR( ret ) = build_relpath( view, table_index, result_index, name );
}
if (type) *type = CIM_STRING;
return S_OK;
@ -772,7 +1012,7 @@ static HRESULT get_system_propval( const struct view *view, UINT index, const WC
if (ret)
{
V_VT( ret ) = VT_BSTR;
V_BSTR( ret ) = build_servername( view );
V_BSTR( ret ) = view->proplist ? NULL : build_servername();
}
if (type) *type = CIM_STRING;
return S_OK;
@ -871,6 +1111,9 @@ void set_variant( VARTYPE type, LONGLONG val, void *val_ptr, VARIANT *ret )
break;
case VT_NULL:
break;
case VT_R4:
V_R4( ret ) = *(FLOAT *)&val;
break;
default:
ERR("unhandled variant type %u\n", type);
return;
@ -878,34 +1121,74 @@ void set_variant( VARTYPE type, LONGLONG val, void *val_ptr, VARIANT *ret )
V_VT( ret ) = type;
}
HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VARIANT *ret,
CIMTYPE *type, LONG *flavor )
static HRESULT map_view_index( const struct view *view, UINT index, UINT *table_index, UINT *result_index )
{
switch (view->type)
{
case VIEW_TYPE_SELECT:
*table_index = 0;
*result_index = index;
break;
case VIEW_TYPE_ASSOCIATORS:
*table_index = *result_index = index;
break;
default:
ERR( "unhandled view type %u\n", view->type );
return WBEM_E_FAILED;
}
return S_OK;
}
struct table *get_view_table( const struct view *view, UINT index )
{
switch (view->type)
{
case VIEW_TYPE_SELECT:
return view->table[0];
case VIEW_TYPE_ASSOCIATORS:
return view->table[index];
default:
ERR( "unhandled view type %u\n", view->type );
return NULL;
}
}
HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VARIANT *ret, CIMTYPE *type,
LONG *flavor )
{
HRESULT hr;
UINT column, row;
UINT column, row, table_index, result_index;
struct table *table;
VARTYPE vartype;
void *val_ptr = NULL;
LONGLONG val;
if (is_system_prop( name )) return get_system_propval( view, index, name, ret, type, flavor );
if (!view->count || !is_selected_prop( view, name )) return WBEM_E_NOT_FOUND;
if ((hr = map_view_index( view, index, &table_index, &result_index )) != S_OK) return hr;
hr = get_column_index( view->table, name, &column );
if (hr != S_OK || is_method( view->table, column )) return WBEM_E_NOT_FOUND;
if (is_system_prop( name )) return get_system_propval( view, table_index, result_index, name, ret, type, flavor );
if (!view->result_count || !is_result_prop( view, name )) return WBEM_E_NOT_FOUND;
row = view->result[index];
hr = get_value( view->table, row, column, &val );
table = view->table[table_index];
hr = get_column_index( table, name, &column );
if (hr != S_OK || is_method( table, column )) return WBEM_E_NOT_FOUND;
row = view->result[result_index];
hr = get_value( table, row, column, &val );
if (hr != S_OK) return hr;
if (type) *type = view->table->columns[column].type & COL_TYPE_MASK;
if (type) *type = table->columns[column].type & COL_TYPE_MASK;
if (flavor) *flavor = 0;
if (!ret) return S_OK;
vartype = view->table->columns[column].vartype;
if (view->table->columns[column].type & CIM_FLAG_ARRAY)
vartype = table->columns[column].vartype;
if (table->columns[column].type & CIM_FLAG_ARRAY)
{
CIMTYPE basetype = view->table->columns[column].type & CIM_TYPE_MASK;
CIMTYPE basetype = table->columns[column].type & CIM_TYPE_MASK;
val_ptr = to_safearray( (const struct array *)(INT_PTR)val, basetype );
if (!val_ptr) vartype = VT_NULL;
@ -914,7 +1197,7 @@ HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VAR
return S_OK;
}
switch (view->table->columns[column].type & COL_TYPE_MASK)
switch (table->columns[column].type & COL_TYPE_MASK)
{
case CIM_BOOLEAN:
if (!vartype) vartype = VT_BOOL;
@ -950,14 +1233,17 @@ HRESULT get_propval( const struct view *view, UINT index, const WCHAR *name, VAR
break;
case CIM_SINT64:
vartype = VT_BSTR;
val_ptr = get_value_bstr( view->table, row, column );
val_ptr = get_value_bstr( table, row, column );
break;
case CIM_UINT64:
vartype = VT_BSTR;
val_ptr = get_value_bstr( view->table, row, column );
val_ptr = get_value_bstr( table, row, column );
break;
case CIM_REAL32:
if (!vartype) vartype = VT_R4;
break;
default:
ERR("unhandled column type %u\n", view->table->columns[column].type);
ERR("unhandled column type %u\n", table->columns[column].type);
return WBEM_E_FAILED;
}
@ -1087,45 +1373,56 @@ HRESULT to_longlong( VARIANT *var, LONGLONG *val, CIMTYPE *type )
HRESULT put_propval( const struct view *view, UINT index, const WCHAR *name, VARIANT *var, CIMTYPE type )
{
HRESULT hr;
UINT column, row = view->result[index];
UINT row, column, table_index, result_index;
struct table *table;
LONGLONG val;
hr = get_column_index( view->table, name, &column );
if ((hr = map_view_index( view, index, &table_index, &result_index )) != S_OK) return hr;
table = view->table[table_index];
hr = get_column_index( table, name, &column );
if (hr != S_OK)
{
FIXME("no support for creating new properties\n");
return WBEM_E_FAILED;
}
if (is_method( view->table, column ) || !(view->table->columns[column].type & COL_FLAG_DYNAMIC))
if (is_method( table, column ) || !(table->columns[column].type & COL_FLAG_DYNAMIC))
return WBEM_E_FAILED;
hr = to_longlong( var, &val, &type );
if (hr != S_OK) return hr;
return set_value( view->table, row, column, val, type );
row = view->result[result_index];
return set_value( table, row, column, val, type );
}
HRESULT get_properties( const struct view *view, LONG flags, SAFEARRAY **props )
HRESULT get_properties( const struct view *view, UINT index, LONG flags, SAFEARRAY **props )
{
SAFEARRAY *sa;
BSTR str;
UINT i, num_props = count_selected_properties( view );
UINT i, table_index, result_index, num_props;
struct table *table;
HRESULT hr;
LONG j;
if ((hr = map_view_index( view, index, &table_index, &result_index )) != S_OK) return hr;
num_props = count_result_properties( view, table_index );
if (!(sa = SafeArrayCreateVector( VT_BSTR, 0, num_props ))) return E_OUTOFMEMORY;
for (i = 0, j = 0; i < view->table->num_cols; i++)
table = view->table[table_index];
for (i = 0, j = 0; i < table->num_cols; i++)
{
BOOL is_system;
if (is_method( view->table, i )) continue;
if (!is_selected_prop( view, view->table->columns[i].name )) continue;
if (is_method( table, i )) continue;
if (!is_result_prop( view, table->columns[i].name )) continue;
is_system = is_system_prop( view->table->columns[i].name );
is_system = is_system_prop( table->columns[i].name );
if ((flags & WBEM_FLAG_NONSYSTEM_ONLY) && is_system) continue;
else if ((flags & WBEM_FLAG_SYSTEM_ONLY) && !is_system) continue;
str = SysAllocString( view->table->columns[i].name );
str = SysAllocString( table->columns[i].name );
if (!str || SafeArrayPutElement( sa, &j, str ) != S_OK)
{
SysFreeString( str );

View File

@ -320,15 +320,7 @@ static HRESULT WINAPI wbem_services_QueryObjectSink(
return WBEM_E_FAILED;
}
struct path
{
WCHAR *class;
UINT class_len;
WCHAR *filter;
UINT filter_len;
};
static HRESULT parse_path( const WCHAR *str, struct path **ret )
HRESULT parse_path( const WCHAR *str, struct path **ret )
{
struct path *path;
const WCHAR *p = str, *q;
@ -397,14 +389,15 @@ static HRESULT parse_path( const WCHAR *str, struct path **ret )
return S_OK;
}
static void free_path( struct path *path )
void free_path( struct path *path )
{
if (!path) return;
heap_free( path->class );
heap_free( path->filter );
heap_free( path );
}
static WCHAR *query_from_path( const struct path *path )
WCHAR *query_from_path( const struct path *path )
{
static const WCHAR selectW[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','%','s',' ',
@ -819,6 +812,7 @@ static HRESULT WINAPI wbem_services_ExecMethod(
struct path *path;
WCHAR *str;
class_method *func;
struct table *table;
HRESULT hr;
TRACE("%p, %s, %s, %08x, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath),
@ -846,10 +840,11 @@ static HRESULT WINAPI wbem_services_ExecMethod(
hr = EnumWbemClassObject_create( query, (void **)&result );
if (hr != S_OK) goto done;
hr = create_class_object( query->view->table->name, result, 0, NULL, &obj );
table = get_view_table( query->view, 0 );
hr = create_class_object( table->name, result, 0, NULL, &obj );
if (hr != S_OK) goto done;
hr = get_method( query->view->table, strMethodName, &func );
hr = get_method( table, strMethodName, &func );
if (hr != S_OK) goto done;
hr = func( obj, pInParams, ppOutParams );

View File

@ -155,15 +155,23 @@ struct keyword
const struct keyword *next;
};
enum view_type
{
VIEW_TYPE_SELECT,
VIEW_TYPE_ASSOCIATORS,
};
struct view
{
enum view_type type;
const WCHAR *path; /* ASSOCIATORS OF query */
const struct keyword *keywordlist;
const struct property *proplist;
struct table *table;
const struct property *proplist; /* SELECT query */
const struct expr *cond;
UINT table_count;
struct table **table;
UINT result_count;
UINT *result;
UINT count;
};
struct query
@ -173,16 +181,29 @@ struct query
struct list mem;
};
struct path
{
WCHAR *class;
UINT class_len;
WCHAR *filter;
UINT filter_len;
};
HRESULT parse_path( const WCHAR *, struct path ** ) DECLSPEC_HIDDEN;
void free_path( struct path * ) DECLSPEC_HIDDEN;
WCHAR *query_from_path( const struct path * ) DECLSPEC_HIDDEN;
struct query *create_query(void) DECLSPEC_HIDDEN;
void free_query( struct query * ) DECLSPEC_HIDDEN;
struct query *addref_query( struct query * ) DECLSPEC_HIDDEN;
void release_query( struct query *query ) DECLSPEC_HIDDEN;
HRESULT exec_query( const WCHAR *, IEnumWbemClassObject ** ) DECLSPEC_HIDDEN;
HRESULT parse_query( const WCHAR *, struct view **, struct list * ) DECLSPEC_HIDDEN;
HRESULT create_view( const WCHAR *, const struct keyword *, const WCHAR *, const struct property *,
HRESULT create_view( enum view_type, const WCHAR *, const struct keyword *, const WCHAR *, const struct property *,
const struct expr *, struct view ** ) DECLSPEC_HIDDEN;
void destroy_view( struct view * ) DECLSPEC_HIDDEN;
HRESULT execute_view( struct view * ) DECLSPEC_HIDDEN;
struct table *get_view_table( const struct view *, UINT ) DECLSPEC_HIDDEN;
void init_table_list( void ) DECLSPEC_HIDDEN;
struct table *grab_table( const WCHAR * ) DECLSPEC_HIDDEN;
struct table *addref_table( struct table * ) DECLSPEC_HIDDEN;
@ -202,15 +223,14 @@ BSTR get_value_bstr( const struct table *, UINT, UINT ) DECLSPEC_HIDDEN;
HRESULT set_value( const struct table *, UINT, UINT, LONGLONG, CIMTYPE ) DECLSPEC_HIDDEN;
BOOL is_method( const struct table *, UINT ) DECLSPEC_HIDDEN;
HRESULT get_method( const struct table *, const WCHAR *, class_method ** ) DECLSPEC_HIDDEN;
HRESULT get_propval( const struct view *, UINT, const WCHAR *, VARIANT *,
CIMTYPE *, LONG * ) DECLSPEC_HIDDEN;
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 to_longlong( VARIANT *, LONGLONG *, CIMTYPE * ) DECLSPEC_HIDDEN;
SAFEARRAY *to_safearray( const struct array *, CIMTYPE ) DECLSPEC_HIDDEN;
VARTYPE to_vartype( CIMTYPE ) DECLSPEC_HIDDEN;
void destroy_array( struct array *, CIMTYPE ) DECLSPEC_HIDDEN;
BOOL is_selected_prop( const struct view *, const WCHAR * ) DECLSPEC_HIDDEN;
HRESULT get_properties( const struct view *, LONG, SAFEARRAY ** ) DECLSPEC_HIDDEN;
BOOL is_result_prop( const struct view *, const WCHAR * ) DECLSPEC_HIDDEN;
HRESULT get_properties( const struct view *, UINT, LONG, SAFEARRAY ** ) DECLSPEC_HIDDEN;
HRESULT get_object( const WCHAR *, IWbemClassObject ** ) DECLSPEC_HIDDEN;
BSTR get_method_name( const WCHAR *, UINT ) DECLSPEC_HIDDEN;
void set_variant( VARTYPE, LONGLONG, void *, VARIANT * ) DECLSPEC_HIDDEN;

View File

@ -289,7 +289,7 @@ associatorsof:
struct parser *parser = ctx;
struct view *view;
hr = create_view( $3, NULL, NULL, NULL, NULL, &view );
hr = create_view( VIEW_TYPE_ASSOCIATORS, $3, NULL, NULL, NULL, NULL, &view );
if (hr != S_OK)
YYABORT;
@ -301,7 +301,7 @@ associatorsof:
struct parser *parser = ctx;
struct view *view;
hr = create_view( $3, $5, NULL, NULL, NULL, &view );
hr = create_view( VIEW_TYPE_ASSOCIATORS, $3, $5, NULL, NULL, NULL, &view );
if (hr != S_OK)
YYABORT;
@ -316,7 +316,7 @@ select:
struct parser *parser = ctx;
struct view *view;
hr = create_view( NULL, NULL, $3, NULL, NULL, &view );
hr = create_view( VIEW_TYPE_SELECT, NULL, NULL, $3, NULL, NULL, &view );
if (hr != S_OK)
YYABORT;
@ -328,7 +328,7 @@ select:
struct parser *parser = ctx;
struct view *view;
hr = create_view( NULL, NULL, $4, $2, NULL, &view );
hr = create_view( VIEW_TYPE_SELECT, NULL, NULL, $4, $2, NULL, &view );
if (hr != S_OK)
YYABORT;
@ -340,7 +340,7 @@ select:
struct parser *parser = ctx;
struct view *view;
hr = create_view( NULL, NULL, $4, $2, $6, &view );
hr = create_view( VIEW_TYPE_SELECT, NULL, NULL, $4, $2, $6, &view );
if (hr != S_OK)
YYABORT;