wbemprox: Add support for parsing 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-06-24 15:15:35 +02:00 committed by Alexandre Julliard
parent 7e14df06f1
commit d83b71ebfd
5 changed files with 179 additions and 45 deletions

View File

@ -30,17 +30,17 @@
WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
HRESULT create_view( const struct property *proplist, const WCHAR *class,
const struct expr *cond, struct view **ret )
HRESULT create_view( 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( sizeof(struct view) );
struct view *view = heap_alloc_zero( sizeof(*view) );
if (!view) return E_OUTOFMEMORY;
view->proplist = proplist;
view->table = grab_table( class );
view->cond = cond;
view->result = NULL;
view->count = 0;
view->path = path;
view->keywordlist = keywordlist;
view->proplist = proplist;
view->table = grab_table( class );
view->cond = cond;
*ret = view;
return S_OK;
}

View File

@ -357,7 +357,7 @@ struct table *grab_table( const WCHAR *name )
LIST_FOR_EACH_ENTRY( table, table_list, struct table, entry )
{
if (!strcmpiW( table->name, name ))
if (name && !strcmpiW( table->name, name ))
{
TRACE("returning %p\n", table);
return addref_table( table );

View File

@ -156,14 +156,37 @@ static void test_select( IWbemServices *services )
static void test_associators( IWbemServices *services )
{
static const WCHAR query1[] =
{'A','S','S','O','C','I','A','T','O','R','S',' ','O','F',' ','{','W','i','n','3','2','_',
{'A','S','S','O','C','I','A','T','O','R','S',' ',' ','O','F','{','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','D','=','"','C',':','"','}',0};
static const WCHAR query2[] =
{'A','S','S','O','C','I','A','T','O','R','S',' ','O','F',' ','{','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','D','=','"','C',':','"','}',' ',
'W','H','E','R','E',' ','A','s','s','o','c','C','l','a','s','s',' ','=',' ','W','i','n','3','2','_',
'W','H','E','R','E',' ','A','s','s','o','c','C','l','a','s','s','=','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','T','o','P','a','r','t','i','t','i','o','n',0};
static const WCHAR *test[] = { query1, query2 };
static const WCHAR query3[] =
{'A','S','S','O','C','I','A','T','O','R','S',' ',' ','O','F',' ','{','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','D','}',0};
static const WCHAR query4[] =
{'A','S','S','O','C','I','A','T','O','R','S',' ',' ','O','F',' ','{','W','i','n','3','2','_',
'D','i','s','k','D','r','i','v','e','.','D','e','v','i','c','e','I','D','=',
'\'','\\','\\','.','\\','P','H','Y','S','I','C','A','L','D','R','I','V','E','0','\'','}',0};
static const WCHAR query5[] =
{'A','S','S','O','C','I','A','T','O','R','S',' ','O','F',' ','{','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','D','=','"','C',':','"','}',' ',
'W','H','E','R','E',' ','A','s','s','o','c','C','l','a','s','s','=','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','T','o','P','a','r','t','i','t','i','o','n',' ',
'C','l','a','s','s','D','e','f','s','O','n','l','y',0};
static const WCHAR query6[] =
{'A','S','S','O','C','I','A','T','O','R','S',' ','O','F',' ','{','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','D','=','"','C',':','"','}',' ',
'W','H','E','R','E',' ','C','l','a','s','s','D','e','f','s','O','n','l','y',0};
static const WCHAR query7[] =
{'A','S','S','O','C','I','A','T','O','R','S',' ','O','F',' ','{','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','.','D','e','v','i','c','e','I','D','=','"','C',':','"','}',' ',
'W','H','E','R','E',' ','C','l','a','s','s','D','e','f','s','O','n','l','y',' ',
'A','s','s','o','c','C','l','a','s','s',' ','=',' ','W','i','n','3','2','_',
'L','o','g','i','c','a','l','D','i','s','k','T','o','P','a','r','t','i','t','i','o','n',0};
static const WCHAR *test[] = { query1, query2, query3, query4, query5, query6, query7 };
HRESULT hr;
IEnumWbemClassObject *result;
UINT i;
@ -171,7 +194,7 @@ static void test_associators( IWbemServices *services )
for (i = 0; i < ARRAY_SIZE( test ); i++)
{
hr = exec_query( services, test[i], &result );
todo_wine ok( hr == S_OK, "query %u failed: %08x\n", i, hr );
ok( hr == S_OK, "query %u failed: %08x\n", i, hr );
if (result) IEnumWbemClassObject_Release( result );
}
}

View File

@ -148,8 +148,17 @@ struct record
struct table *table;
};
struct keyword
{
const WCHAR *name;
const WCHAR *value;
const struct keyword *next;
};
struct view
{
const WCHAR *path; /* ASSOCIATORS OF query */
const struct keyword *keywordlist;
const struct property *proplist;
struct table *table;
const struct expr *cond;
@ -170,8 +179,8 @@ 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 struct property *, const WCHAR *, const struct expr *,
struct view ** ) DECLSPEC_HIDDEN;
HRESULT create_view( 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;
void init_table_list( void ) DECLSPEC_HIDDEN;

View File

@ -67,6 +67,18 @@ static struct property *alloc_property( struct parser *parser, const WCHAR *clas
return prop;
}
static struct keyword *alloc_keyword( struct parser *parser, const WCHAR *name, const WCHAR *value )
{
struct keyword *keyword = alloc_mem( parser, sizeof(*keyword) );
if (keyword)
{
keyword->name = name;
keyword->value = value;
keyword->next = NULL;
}
return keyword;
}
static WCHAR *get_string( struct parser *parser, const struct string *str )
{
const WCHAR *p = str->data;
@ -87,6 +99,18 @@ static WCHAR *get_string( struct parser *parser, const struct string *str )
return ret;
}
static WCHAR *get_path( struct parser *parser, const struct string *str )
{
const WCHAR *p = str->data;
int len = str->len;
WCHAR *ret;
if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL;
memcpy( ret, p, len * sizeof(WCHAR) );
ret[len] = 0;
return ret;
}
static int get_int( struct parser *parser )
{
const WCHAR *p = &parser->cmd[parser->idx];
@ -195,28 +219,92 @@ static int wql_lex( void *val, struct parser *parser );
struct string str;
WCHAR *string;
struct property *proplist;
struct keyword *keywordlist;
struct view *view;
struct expr *expr;
int integer;
}
%token TK_SELECT TK_FROM TK_STAR TK_COMMA TK_DOT TK_IS TK_LP TK_RP TK_NULL TK_FALSE TK_TRUE
%token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY
%token <str> TK_STRING TK_ID
%token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY TK_ASSOCIATORS TK_OF
%token <str> TK_STRING TK_ID TK_PATH
%type <string> id
%type <string> id path
%type <proplist> prop proplist
%type <view> select
%type <keywordlist> keyword keywordlist
%type <view> query select associatorsof
%type <expr> expr prop_val const_val string_val
%type <integer> number
%left TK_OR
%left TK_AND
%left TK_NOT
%left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
%left TK_OR TK_AND TK_NOT TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
%%
query:
select
|
associatorsof
;
path:
TK_PATH
{
$$ = get_path( ctx, &$1 );
if (!$$)
YYABORT;
}
;
keyword:
id
{
$$ = alloc_keyword( ctx, $1, NULL );
if (!$$)
YYABORT;
}
| id TK_EQ id
{
$$ = alloc_keyword( ctx, $1, $3 );
if (!$$)
YYABORT;
}
;
keywordlist:
keyword
| keyword keywordlist
{
$1->next = $2;
}
;
associatorsof:
TK_ASSOCIATORS TK_OF path
{
HRESULT hr;
struct parser *parser = ctx;
struct view *view;
hr = create_view( $3, NULL, NULL, NULL, NULL, &view );
if (hr != S_OK)
YYABORT;
PARSER_BUBBLE_UP_VIEW( parser, $$, view );
}
| TK_ASSOCIATORS TK_OF path TK_WHERE keywordlist
{
HRESULT hr;
struct parser *parser = ctx;
struct view *view;
hr = create_view( $3, $5, NULL, NULL, NULL, &view );
if (hr != S_OK)
YYABORT;
PARSER_BUBBLE_UP_VIEW( parser, $$, view );
}
;
select:
TK_SELECT TK_FROM id
{
@ -224,7 +312,7 @@ select:
struct parser *parser = ctx;
struct view *view;
hr = create_view( NULL, $3, NULL, &view );
hr = create_view( NULL, NULL, $3, NULL, NULL, &view );
if (hr != S_OK)
YYABORT;
@ -236,7 +324,7 @@ select:
struct parser *parser = ctx;
struct view *view;
hr = create_view( $2, $4, NULL, &view );
hr = create_view( NULL, NULL, $4, $2, NULL, &view );
if (hr != S_OK)
YYABORT;
@ -248,7 +336,7 @@ select:
struct parser *parser = ctx;
struct view *view;
hr = create_view( $2, $4, $6, &view );
hr = create_view( NULL, NULL, $4, $2, $6, &view );
if (hr != S_OK)
YYABORT;
@ -535,16 +623,18 @@ static const char id_char[] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
struct keyword
struct wql_keyword
{
const WCHAR *name;
unsigned int len;
int type;
};
#define MAX_TOKEN_LEN 6
#define MIN_TOKEN_LEN 2
#define MAX_TOKEN_LEN 11
static const WCHAR andW[] = {'A','N','D'};
static const WCHAR associatorsW[] = {'A','S','S','O','C','I','A','T','O','R','S'};
static const WCHAR byW[] = {'B','Y'};
static const WCHAR falseW[] = {'F','A','L','S','E'};
static const WCHAR fromW[] = {'F','R','O','M'};
@ -552,30 +642,33 @@ static const WCHAR isW[] = {'I','S'};
static const WCHAR likeW[] = {'L','I','K','E'};
static const WCHAR notW[] = {'N','O','T'};
static const WCHAR nullW[] = {'N','U','L','L'};
static const WCHAR ofW[] = {'O','F'};
static const WCHAR orW[] = {'O','R'};
static const WCHAR selectW[] = {'S','E','L','E','C','T'};
static const WCHAR trueW[] = {'T','R','U','E'};
static const WCHAR whereW[] = {'W','H','E','R','E'};
static const struct keyword keyword_table[] =
static const struct wql_keyword keyword_table[] =
{
{ andW, ARRAY_SIZE(andW), TK_AND },
{ byW, ARRAY_SIZE(byW), TK_BY },
{ falseW, ARRAY_SIZE(falseW), TK_FALSE },
{ fromW, ARRAY_SIZE(fromW), TK_FROM },
{ isW, ARRAY_SIZE(isW), TK_IS },
{ likeW, ARRAY_SIZE(likeW), TK_LIKE },
{ notW, ARRAY_SIZE(notW), TK_NOT },
{ nullW, ARRAY_SIZE(nullW), TK_NULL },
{ orW, ARRAY_SIZE(orW), TK_OR },
{ selectW, ARRAY_SIZE(selectW), TK_SELECT },
{ trueW, ARRAY_SIZE(trueW), TK_TRUE },
{ whereW, ARRAY_SIZE(whereW), TK_WHERE }
{ andW, ARRAY_SIZE(andW), TK_AND },
{ associatorsW, ARRAY_SIZE(associatorsW), TK_ASSOCIATORS },
{ byW, ARRAY_SIZE(byW), TK_BY },
{ falseW, ARRAY_SIZE(falseW), TK_FALSE },
{ fromW, ARRAY_SIZE(fromW), TK_FROM },
{ isW, ARRAY_SIZE(isW), TK_IS },
{ likeW, ARRAY_SIZE(likeW), TK_LIKE },
{ notW, ARRAY_SIZE(notW), TK_NOT },
{ nullW, ARRAY_SIZE(nullW), TK_NULL },
{ ofW, ARRAY_SIZE(ofW), TK_OF },
{ orW, ARRAY_SIZE(orW), TK_OR },
{ selectW, ARRAY_SIZE(selectW), TK_SELECT },
{ trueW, ARRAY_SIZE(trueW), TK_TRUE },
{ whereW, ARRAY_SIZE(whereW), TK_WHERE }
};
static int cmp_keyword( const void *arg1, const void *arg2 )
{
const struct keyword *key1 = arg1, *key2 = arg2;
const struct wql_keyword *key1 = arg1, *key2 = arg2;
int len = min( key1->len, key2->len );
int ret;
@ -587,14 +680,14 @@ static int cmp_keyword( const void *arg1, const void *arg2 )
static int keyword_type( const WCHAR *str, unsigned int len )
{
struct keyword key, *ret;
struct wql_keyword key, *ret;
if (len > MAX_TOKEN_LEN) return TK_ID;
if (len < MIN_TOKEN_LEN || len > MAX_TOKEN_LEN) return TK_ID;
key.name = str;
key.len = len;
key.type = 0;
ret = bsearch( &key, keyword_table, ARRAY_SIZE(keyword_table), sizeof(struct keyword), cmp_keyword );
ret = bsearch( &key, keyword_table, ARRAY_SIZE(keyword_table), sizeof(struct wql_keyword), cmp_keyword );
if (ret) return ret->type;
return TK_ID;
}
@ -622,6 +715,15 @@ static int get_token( const WCHAR *s, int *token )
case ')':
*token = TK_RP;
return 1;
case '{':
for (i = 1; s[i] && s[i] != '}'; i++) {}
if (s[i] != '}')
{
*token = TK_ILLEGAL;
return i;
}
*token = TK_PATH;
return i + 1;
case '*':
*token = TK_STAR;
return 1;