Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/wbemprox/builtin.c | 40 ++-
dlls/wbemprox/class.c | 36 ++-
dlls/wbemprox/query.c | 509 ++++++++++++++++++++++++-------
dlls/wbemprox/services.c | 21 +-
dlls/wbemprox/wbemprox_private.h | 36 ++-
dlls/wbemprox/wql.y | 10 +-
6 files changed, 496 insertions(+), 156 deletions(-)
diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c
index de793f3f7e..8bb5be0aac 100644
--- a/dlls/wbemprox/builtin.c
+++ b/dlls/wbemprox/builtin.c
@@ -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 },
diff --git a/dlls/wbemprox/class.c b/dlls/wbemprox/class.c
index d0522787a2..5f8dcea10d 100644
--- a/dlls/wbemprox/class.c
+++ b/dlls/wbemprox/class.c
@@ -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 );
}
diff --git a/dlls/wbemprox/query.c b/dlls/wbemprox/query.c
index 7b194fbabf..b311fdaf2d 100644
--- a/dlls/wbemprox/query.c
+++ b/dlls/wbemprox/query.c
@@ -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 );
diff --git a/dlls/wbemprox/services.c b/dlls/wbemprox/services.c
index 0af02a4a1d..e1cd2466e4 100644
--- a/dlls/wbemprox/services.c
+++ b/dlls/wbemprox/services.c
@@ -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 );
diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h
index c1b1ae8679..7e61cf5ead 100644
--- a/dlls/wbemprox/wbemprox_private.h
+++ b/dlls/wbemprox/wbemprox_private.h
@@ -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;
diff --git a/dlls/wbemprox/wql.y b/dlls/wbemprox/wql.y
index 99279149ae..12f4cb5104 100644
--- a/dlls/wbemprox/wql.y
+++ b/dlls/wbemprox/wql.y
@@ -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;
--
2.20.1