Signed-off-by: Hans Leidekker hans@codeweavers.com --- 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 d193574a39..3221e27b0b 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 ad56e0c7ba..a8fd0041b3 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 052e8a2778..2c1ca7f91d 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 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 }; + 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 d52affa82a..15b961de52 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 236a37d9f7..85d4339e8d 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 <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] != '}'; i++) {} + if (s[i] != '}') + { + *token = TK_ILLEGAL; + return i; + } + *token = TK_PATH; + return i + 1; case '*': *token = TK_STAR; return 1;