From 8487265f81a2824ae26485db3b7525c3984efca6 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Tue, 10 Sep 2019 17:09:14 +0200 Subject: [PATCH] wbemprox: Add support for evaluating ASSOCIATORS OF queries. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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 de793f3f7ef..8bb5be0aac0 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 d0522787a20..5f8dcea10dc 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 7b194fbabfc..b311fdaf2d2 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 0af02a4a1d8..e1cd2466e4c 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 c1b1ae86794..7e61cf5eadf 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 99279149ae6..12f4cb5104f 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;