From d83b71ebfdfe83704c313d7c11e8c87c9a8b0419 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 24 Jun 2019 15:15:35 +0200 Subject: [PATCH] wbemprox: Add support for parsing ASSOCIATORS OF queries. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/wbemprox/query.c | 16 +-- dlls/wbemprox/table.c | 2 +- dlls/wbemprox/tests/query.c | 31 +++++- dlls/wbemprox/wbemprox_private.h | 13 ++- dlls/wbemprox/wql.y | 162 +++++++++++++++++++++++++------ 5 files changed, 179 insertions(+), 45 deletions(-) diff --git a/dlls/wbemprox/query.c b/dlls/wbemprox/query.c index d193574a393..3221e27b0bb 100644 --- a/dlls/wbemprox/query.c +++ b/dlls/wbemprox/query.c @@ -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; } diff --git a/dlls/wbemprox/table.c b/dlls/wbemprox/table.c index ad56e0c7bab..a8fd0041b3c 100644 --- a/dlls/wbemprox/table.c +++ b/dlls/wbemprox/table.c @@ -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 ); diff --git a/dlls/wbemprox/tests/query.c b/dlls/wbemprox/tests/query.c index 052e8a27781..2c1ca7f91df 100644 --- a/dlls/wbemprox/tests/query.c +++ b/dlls/wbemprox/tests/query.c @@ -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 ); } } diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h index d52affa82af..15b961de52b 100644 --- a/dlls/wbemprox/wbemprox_private.h +++ b/dlls/wbemprox/wbemprox_private.h @@ -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; diff --git a/dlls/wbemprox/wql.y b/dlls/wbemprox/wql.y index 236a37d9f73..4d9ba493f01 100644 --- a/dlls/wbemprox/wql.y +++ b/dlls/wbemprox/wql.y @@ -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 TK_STRING TK_ID +%token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY TK_ASSOCIATORS TK_OF +%token TK_STRING TK_ID TK_PATH -%type id +%type id path %type prop proplist -%type select +%type keyword keywordlist +%type query select associatorsof %type expr prop_val const_val string_val %type 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;