[PATCH] wbemprox: Add support for parsing ASSOCIATORS OF queries.

Hans Leidekker hans at codeweavers.com
Mon Jun 24 07:32:33 CDT 2019


Signed-off-by: Hans Leidekker <hans at 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;
-- 
2.11.0




More information about the wine-devel mailing list