v2: Add missing null test.
Thanks Jacek.
Signed-off-by: Hans Leidekker <hans(a)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..4d9ba493f0 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] && 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