1 %{ 2 3 /* 4 * Copyright 2012 Hans Leidekker for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "config.h" 22 #include <stdarg.h> 23 24 #include "windef.h" 25 #include "winbase.h" 26 #include "wbemcli.h" 27 #include "wbemprox_private.h" 28 29 #include "wine/list.h" 30 #include "wine/debug.h" 31 #include "wine/unicode.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox); 34 35 struct parser 36 { 37 const WCHAR *cmd; 38 UINT idx; 39 UINT len; 40 HRESULT error; 41 struct view **view; 42 struct list *mem; 43 }; 44 45 struct string 46 { 47 const WCHAR *data; 48 int len; 49 }; 50 51 static void *alloc_mem( struct parser *parser, UINT size ) 52 { 53 struct list *mem = heap_alloc( sizeof(struct list) + size ); 54 list_add_tail( parser->mem, mem ); 55 return &mem[1]; 56 } 57 58 static struct property *alloc_property( struct parser *parser, const WCHAR *class, const WCHAR *name ) 59 { 60 struct property *prop = alloc_mem( parser, sizeof(*prop) ); 61 if (prop) 62 { 63 prop->name = name; 64 prop->class = class; 65 prop->next = NULL; 66 } 67 return prop; 68 } 69 70 static WCHAR *get_string( struct parser *parser, const struct string *str ) 71 { 72 const WCHAR *p = str->data; 73 int len = str->len; 74 WCHAR *ret; 75 76 if ((p[0] == '\"' && p[len - 1] != '\"') || 77 (p[0] == '\'' && p[len - 1] != '\'')) return NULL; 78 if ((p[0] == '\"' && p[len - 1] == '\"') || 79 (p[0] == '\'' && p[len - 1] == '\'')) 80 { 81 p++; 82 len -= 2; 83 } 84 if (!(ret = alloc_mem( parser, (len + 1) * sizeof(WCHAR) ))) return NULL; 85 memcpy( ret, p, len * sizeof(WCHAR) ); 86 ret[len] = 0; 87 return ret; 88 } 89 90 static int get_int( struct parser *parser ) 91 { 92 const WCHAR *p = &parser->cmd[parser->idx]; 93 int i, ret = 0; 94 95 for (i = 0; i < parser->len; i++) 96 { 97 if (p[i] < '0' || p[i] > '9') 98 { 99 ERR("should only be numbers here!\n"); 100 break; 101 } 102 ret = (p[i] - '0') + ret * 10; 103 } 104 return ret; 105 } 106 107 static struct expr *expr_complex( struct parser *parser, struct expr *l, UINT op, struct expr *r ) 108 { 109 struct expr *e = alloc_mem( parser, sizeof(*e) ); 110 if (e) 111 { 112 e->type = EXPR_COMPLEX; 113 e->u.expr.left = l; 114 e->u.expr.op = op; 115 e->u.expr.right = r; 116 } 117 return e; 118 } 119 120 static struct expr *expr_unary( struct parser *parser, struct expr *l, UINT op ) 121 { 122 struct expr *e = alloc_mem( parser, sizeof(*e) ); 123 if (e) 124 { 125 e->type = EXPR_UNARY; 126 e->u.expr.left = l; 127 e->u.expr.op = op; 128 e->u.expr.right = NULL; 129 } 130 return e; 131 } 132 133 static struct expr *expr_ival( struct parser *parser, int val ) 134 { 135 struct expr *e = alloc_mem( parser, sizeof *e ); 136 if (e) 137 { 138 e->type = EXPR_IVAL; 139 e->u.ival = val; 140 } 141 return e; 142 } 143 144 static struct expr *expr_sval( struct parser *parser, const struct string *str ) 145 { 146 struct expr *e = alloc_mem( parser, sizeof *e ); 147 if (e) 148 { 149 e->type = EXPR_SVAL; 150 e->u.sval = get_string( parser, str ); 151 if (!e->u.sval) 152 return NULL; /* e will be freed by query destructor */ 153 } 154 return e; 155 } 156 157 static struct expr *expr_bval( struct parser *parser, int val ) 158 { 159 struct expr *e = alloc_mem( parser, sizeof *e ); 160 if (e) 161 { 162 e->type = EXPR_BVAL; 163 e->u.ival = val; 164 } 165 return e; 166 } 167 168 static struct expr *expr_propval( struct parser *parser, const struct property *prop ) 169 { 170 struct expr *e = alloc_mem( parser, sizeof *e ); 171 if (e) 172 { 173 e->type = EXPR_PROPVAL; 174 e->u.propval = prop; 175 } 176 return e; 177 } 178 179 static int wql_error( struct parser *parser, const char *str ); 180 static int wql_lex( void *val, struct parser *parser ); 181 182 #define PARSER_BUBBLE_UP_VIEW( parser, result, current_view ) \ 183 *parser->view = current_view; \ 184 result = current_view 185 186 %} 187 188 %lex-param { struct parser *ctx } 189 %parse-param { struct parser *ctx } 190 %error-verbose 191 %pure-parser 192 193 %union 194 { 195 struct string str; 196 WCHAR *string; 197 struct property *proplist; 198 struct view *view; 199 struct expr *expr; 200 int integer; 201 } 202 203 %token TK_SELECT TK_FROM TK_STAR TK_COMMA TK_DOT TK_IS TK_LP TK_RP TK_NULL TK_FALSE TK_TRUE 204 %token TK_INTEGER TK_WHERE TK_SPACE TK_MINUS TK_ILLEGAL TK_BY 205 %token <str> TK_STRING TK_ID 206 207 %type <string> id 208 %type <proplist> prop proplist 209 %type <view> select 210 %type <expr> expr prop_val const_val string_val 211 %type <integer> number 212 213 %left TK_OR 214 %left TK_AND 215 %left TK_NOT 216 %left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE 217 218 %% 219 220 select: 221 TK_SELECT TK_FROM id 222 { 223 HRESULT hr; 224 struct parser *parser = ctx; 225 struct view *view; 226 227 hr = create_view( NULL, $3, NULL, &view ); 228 if (hr != S_OK) 229 YYABORT; 230 231 PARSER_BUBBLE_UP_VIEW( parser, $$, view ); 232 } 233 | TK_SELECT proplist TK_FROM id 234 { 235 HRESULT hr; 236 struct parser *parser = ctx; 237 struct view *view; 238 239 hr = create_view( $2, $4, NULL, &view ); 240 if (hr != S_OK) 241 YYABORT; 242 243 PARSER_BUBBLE_UP_VIEW( parser, $$, view ); 244 } 245 | TK_SELECT proplist TK_FROM id TK_WHERE expr 246 { 247 HRESULT hr; 248 struct parser *parser = ctx; 249 struct view *view; 250 251 hr = create_view( $2, $4, $6, &view ); 252 if (hr != S_OK) 253 YYABORT; 254 255 PARSER_BUBBLE_UP_VIEW( parser, $$, view ); 256 } 257 ; 258 259 proplist: 260 prop 261 | prop TK_COMMA proplist 262 { 263 $1->next = $3; 264 } 265 | TK_STAR 266 { 267 $$ = NULL; 268 } 269 ; 270 271 prop: 272 id TK_DOT id 273 { 274 $$ = alloc_property( ctx, $1, $3 ); 275 if (!$$) 276 YYABORT; 277 } 278 | id 279 { 280 $$ = alloc_property( ctx, NULL, $1 ); 281 if (!$$) 282 YYABORT; 283 } 284 ; 285 286 id: 287 TK_ID 288 { 289 $$ = get_string( ctx, &$1 ); 290 if (!$$) 291 YYABORT; 292 } 293 ; 294 295 number: 296 TK_INTEGER 297 { 298 $$ = get_int( ctx ); 299 } 300 ; 301 302 expr: 303 TK_LP expr TK_RP 304 { 305 $$ = $2; 306 if (!$$) 307 YYABORT; 308 } 309 | expr TK_AND expr 310 { 311 $$ = expr_complex( ctx, $1, OP_AND, $3 ); 312 if (!$$) 313 YYABORT; 314 } 315 | expr TK_OR expr 316 { 317 $$ = expr_complex( ctx, $1, OP_OR, $3 ); 318 if (!$$) 319 YYABORT; 320 } 321 | TK_NOT expr 322 { 323 $$ = expr_unary( ctx, $2, OP_NOT ); 324 if (!$$) 325 YYABORT; 326 } 327 | prop_val TK_EQ const_val 328 { 329 $$ = expr_complex( ctx, $1, OP_EQ, $3 ); 330 if (!$$) 331 YYABORT; 332 } 333 | prop_val TK_GT const_val 334 { 335 $$ = expr_complex( ctx, $1, OP_GT, $3 ); 336 if (!$$) 337 YYABORT; 338 } 339 | prop_val TK_LT const_val 340 { 341 $$ = expr_complex( ctx, $1, OP_LT, $3 ); 342 if (!$$) 343 YYABORT; 344 } 345 | prop_val TK_LE const_val 346 { 347 $$ = expr_complex( ctx, $1, OP_LE, $3 ); 348 if (!$$) 349 YYABORT; 350 } 351 | prop_val TK_GE const_val 352 { 353 $$ = expr_complex( ctx, $1, OP_GE, $3 ); 354 if (!$$) 355 YYABORT; 356 } 357 | prop_val TK_NE const_val 358 { 359 $$ = expr_complex( ctx, $1, OP_NE, $3 ); 360 if (!$$) 361 YYABORT; 362 } 363 | const_val TK_EQ prop_val 364 { 365 $$ = expr_complex( ctx, $1, OP_EQ, $3 ); 366 if (!$$) 367 YYABORT; 368 } 369 | const_val TK_GT prop_val 370 { 371 $$ = expr_complex( ctx, $1, OP_GT, $3 ); 372 if (!$$) 373 YYABORT; 374 } 375 | const_val TK_LT prop_val 376 { 377 $$ = expr_complex( ctx, $1, OP_LT, $3 ); 378 if (!$$) 379 YYABORT; 380 } 381 | const_val TK_LE prop_val 382 { 383 $$ = expr_complex( ctx, $1, OP_LE, $3 ); 384 if (!$$) 385 YYABORT; 386 } 387 | const_val TK_GE prop_val 388 { 389 $$ = expr_complex( ctx, $1, OP_GE, $3 ); 390 if (!$$) 391 YYABORT; 392 } 393 | const_val TK_NE prop_val 394 { 395 $$ = expr_complex( ctx, $1, OP_NE, $3 ); 396 if (!$$) 397 YYABORT; 398 } 399 | prop_val TK_LIKE string_val 400 { 401 $$ = expr_complex( ctx, $1, OP_LIKE, $3 ); 402 if (!$$) 403 YYABORT; 404 } 405 | prop_val TK_IS TK_NULL 406 { 407 $$ = expr_unary( ctx, $1, OP_ISNULL ); 408 if (!$$) 409 YYABORT; 410 } 411 | prop_val TK_IS TK_NOT TK_NULL 412 { 413 $$ = expr_unary( ctx, $1, OP_NOTNULL ); 414 if (!$$) 415 YYABORT; 416 } 417 | prop_val TK_EQ TK_NULL 418 { 419 $$ = expr_unary( ctx, $1, OP_ISNULL ); 420 if (!$$) 421 YYABORT; 422 } 423 | TK_NULL TK_EQ prop_val 424 { 425 $$ = expr_unary( ctx, $3, OP_ISNULL ); 426 if (!$$) 427 YYABORT; 428 } 429 | prop_val TK_NE TK_NULL 430 { 431 $$ = expr_unary( ctx, $1, OP_NOTNULL ); 432 if (!$$) 433 YYABORT; 434 } 435 | TK_NULL TK_NE prop_val 436 { 437 $$ = expr_unary( ctx, $3, OP_NOTNULL ); 438 if (!$$) 439 YYABORT; 440 } 441 ; 442 443 string_val: 444 TK_STRING 445 { 446 $$ = expr_sval( ctx, &$1 ); 447 if (!$$) 448 YYABORT; 449 } 450 ; 451 452 prop_val: 453 prop 454 { 455 $$ = expr_propval( ctx, $1 ); 456 if (!$$) 457 YYABORT; 458 } 459 ; 460 461 const_val: 462 number 463 { 464 $$ = expr_ival( ctx, $1 ); 465 if (!$$) 466 YYABORT; 467 } 468 | TK_STRING 469 { 470 $$ = expr_sval( ctx, &$1 ); 471 if (!$$) 472 YYABORT; 473 } 474 | TK_TRUE 475 { 476 $$ = expr_bval( ctx, -1 ); 477 if (!$$) 478 YYABORT; 479 } 480 | TK_FALSE 481 { 482 $$ = expr_bval( ctx, 0 ); 483 if (!$$) 484 YYABORT; 485 } 486 ; 487 488 %% 489 490 HRESULT parse_query( const WCHAR *str, struct view **view, struct list *mem ) 491 { 492 struct parser parser; 493 int ret; 494 495 *view = NULL; 496 497 parser.cmd = str; 498 parser.idx = 0; 499 parser.len = 0; 500 parser.error = WBEM_E_INVALID_QUERY; 501 parser.view = view; 502 parser.mem = mem; 503 504 ret = wql_parse( &parser ); 505 TRACE("wql_parse returned %d\n", ret); 506 if (ret) 507 { 508 if (*parser.view) 509 { 510 destroy_view( *parser.view ); 511 *parser.view = NULL; 512 } 513 return parser.error; 514 } 515 return S_OK; 516 } 517 518 static const char id_char[] = 519 { 520 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 521 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 522 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 523 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 524 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 525 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 526 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 527 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 528 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 529 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 530 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 531 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 532 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 533 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 534 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 535 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 536 }; 537 538 struct keyword 539 { 540 const WCHAR *name; 541 unsigned int len; 542 int type; 543 }; 544 545 #define MAX_TOKEN_LEN 6 546 547 static const WCHAR andW[] = {'A','N','D'}; 548 static const WCHAR byW[] = {'B','Y'}; 549 static const WCHAR falseW[] = {'F','A','L','S','E'}; 550 static const WCHAR fromW[] = {'F','R','O','M'}; 551 static const WCHAR isW[] = {'I','S'}; 552 static const WCHAR likeW[] = {'L','I','K','E'}; 553 static const WCHAR notW[] = {'N','O','T'}; 554 static const WCHAR nullW[] = {'N','U','L','L'}; 555 static const WCHAR orW[] = {'O','R'}; 556 static const WCHAR selectW[] = {'S','E','L','E','C','T'}; 557 static const WCHAR trueW[] = {'T','R','U','E'}; 558 static const WCHAR whereW[] = {'W','H','E','R','E'}; 559 560 static const struct keyword keyword_table[] = 561 { 562 { andW, SIZEOF(andW), TK_AND }, 563 { byW, SIZEOF(byW), TK_BY }, 564 { falseW, SIZEOF(falseW), TK_FALSE }, 565 { fromW, SIZEOF(fromW), TK_FROM }, 566 { isW, SIZEOF(isW), TK_IS }, 567 { likeW, SIZEOF(likeW), TK_LIKE }, 568 { notW, SIZEOF(notW), TK_NOT }, 569 { nullW, SIZEOF(nullW), TK_NULL }, 570 { orW, SIZEOF(orW), TK_OR }, 571 { selectW, SIZEOF(selectW), TK_SELECT }, 572 { trueW, SIZEOF(trueW), TK_TRUE }, 573 { whereW, SIZEOF(whereW), TK_WHERE } 574 }; 575 576 static int cmp_keyword( const void *arg1, const void *arg2 ) 577 { 578 const struct keyword *key1 = arg1, *key2 = arg2; 579 int len = min( key1->len, key2->len ); 580 int ret; 581 582 if ((ret = memicmpW( key1->name, key2->name, len ))) return ret; 583 if (key1->len < key2->len) return -1; 584 else if (key1->len > key2->len) return 1; 585 return 0; 586 } 587 588 static int keyword_type( const WCHAR *str, unsigned int len ) 589 { 590 struct keyword key, *ret; 591 592 if (len > MAX_TOKEN_LEN) return TK_ID; 593 594 key.name = str; 595 key.len = len; 596 key.type = 0; 597 ret = bsearch( &key, keyword_table, SIZEOF(keyword_table), sizeof(struct keyword), cmp_keyword ); 598 if (ret) return ret->type; 599 return TK_ID; 600 } 601 602 static int get_token( const WCHAR *s, int *token ) 603 { 604 int i; 605 606 switch (*s) 607 { 608 case ' ': 609 case '\t': 610 case '\r': 611 case '\n': 612 for (i = 1; isspaceW( s[i] ); i++) {} 613 *token = TK_SPACE; 614 return i; 615 case '-': 616 if (!s[1]) return -1; 617 *token = TK_MINUS; 618 return 1; 619 case '(': 620 *token = TK_LP; 621 return 1; 622 case ')': 623 *token = TK_RP; 624 return 1; 625 case '*': 626 *token = TK_STAR; 627 return 1; 628 case '=': 629 *token = TK_EQ; 630 return 1; 631 case '<': 632 if (s[1] == '=' ) 633 { 634 *token = TK_LE; 635 return 2; 636 } 637 else if (s[1] == '>') 638 { 639 *token = TK_NE; 640 return 2; 641 } 642 else 643 { 644 *token = TK_LT; 645 return 1; 646 } 647 case '>': 648 if (s[1] == '=') 649 { 650 *token = TK_GE; 651 return 2; 652 } 653 else 654 { 655 *token = TK_GT; 656 return 1; 657 } 658 case '!': 659 if (s[1] != '=') 660 { 661 *token = TK_ILLEGAL; 662 return 2; 663 } 664 else 665 { 666 *token = TK_NE; 667 return 2; 668 } 669 case ',': 670 *token = TK_COMMA; 671 return 1; 672 case '\"': 673 case '\'': 674 for (i = 1; s[i]; i++) 675 { 676 if (s[i] == s[0]) break; 677 } 678 if (s[i]) i++; 679 *token = TK_STRING; 680 return i; 681 case '.': 682 if (!isdigitW( s[1] )) 683 { 684 *token = TK_DOT; 685 return 1; 686 } 687 /* fall through */ 688 case '0': case '1': case '2': case '3': case '4': 689 case '5': case '6': case '7': case '8': case '9': 690 *token = TK_INTEGER; 691 for (i = 1; isdigitW( s[i] ); i++) {} 692 return i; 693 default: 694 if (!id_char[*s]) break; 695 696 for (i = 1; id_char[s[i]]; i++) {} 697 *token = keyword_type( s, i ); 698 return i; 699 } 700 *token = TK_ILLEGAL; 701 return 1; 702 } 703 704 static int wql_lex( void *p, struct parser *parser ) 705 { 706 struct string *str = p; 707 int token = -1; 708 do 709 { 710 parser->idx += parser->len; 711 if (!parser->cmd[parser->idx]) return 0; 712 parser->len = get_token( &parser->cmd[parser->idx], &token ); 713 if (!parser->len) break; 714 715 str->data = &parser->cmd[parser->idx]; 716 str->len = parser->len; 717 } while (token == TK_SPACE); 718 return token; 719 } 720 721 static int wql_error( struct parser *parser, const char *str ) 722 { 723 ERR("%s\n", str); 724 return 0; 725 } 726