ReactOS 0.4.16-dev-401-g45b008d
where.c
Go to the documentation of this file.
1/*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2002 Mike McCormack for CodeWeavers
5 * Copyright 2011 Bernhard Loos
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include <stdarg.h>
23#include <assert.h>
24
25#include "windef.h"
26#include "winbase.h"
27#include "winerror.h"
28#include "wine/debug.h"
29#include "msi.h"
30#include "msiquery.h"
31#include "objbase.h"
32#include "objidl.h"
33#include "msipriv.h"
34#include "winnls.h"
35
36#include "query.h"
37
39
40/* below is the query interface to a table */
42{
43 struct tagMSIWHEREVIEW *wv; /* used during sorting */
45};
46
48{
54};
55
56typedef struct tagMSIORDERINFO
57{
62
63typedef struct tagMSIWHEREVIEW
64{
72 UINT reorder_size; /* number of entries available in reorder */
73 struct expr *cond;
77
78static UINT WHERE_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
79 struct expr *cond, INT *val, MSIRECORD *record );
80
81#define INITIAL_REORDER_SIZE 16
82
83#define INVALID_ROW_INDEX (-1)
84
85static void free_reorder(MSIWHEREVIEW *wv)
86{
87 UINT i;
88
89 if (!wv->reorder)
90 return;
91
92 for (i = 0; i < wv->row_count; i++)
93 free(wv->reorder[i]);
94
95 free(wv->reorder);
96 wv->reorder = NULL;
97 wv->reorder_size = 0;
98 wv->row_count = 0;
99}
100
102{
103 struct row_entry **new = calloc(INITIAL_REORDER_SIZE, sizeof(*new));
104 if (!new)
105 return ERROR_OUTOFMEMORY;
106
108
109 wv->reorder = new;
110 wv->reorder_size = INITIAL_REORDER_SIZE;
111
112 return ERROR_SUCCESS;
113}
114
116{
117 if (row >= wv->row_count)
118 return ERROR_NO_MORE_ITEMS;
119
120 *values = wv->reorder[row]->values;
121
122 return ERROR_SUCCESS;
123}
124
126{
127 struct row_entry *new;
128
129 if (wv->reorder_size <= wv->row_count)
130 {
131 struct row_entry **new_reorder;
132 UINT newsize = wv->reorder_size * 2;
133
134 new_reorder = realloc(wv->reorder, newsize * sizeof(*new_reorder));
135 if (!new_reorder)
136 return ERROR_OUTOFMEMORY;
137 memset(new_reorder + wv->reorder_size, 0, (newsize - wv->reorder_size) * sizeof(*new_reorder));
138
139 wv->reorder = new_reorder;
140 wv->reorder_size = newsize;
141 }
142
143 new = malloc(offsetof(struct row_entry, values[wv->table_count]));
144
145 if (!new)
146 return ERROR_OUTOFMEMORY;
147
148 wv->reorder[wv->row_count++] = new;
149
150 memcpy(new->values, vals, wv->table_count * sizeof(UINT));
151 new->wv = wv;
152
153 return ERROR_SUCCESS;
154}
155
156static struct join_table *find_table(MSIWHEREVIEW *wv, UINT col, UINT *table_col)
157{
158 struct join_table *table = wv->tables;
159
160 if(col == 0 || col > wv->col_count)
161 return NULL;
162
163 while (col > table->col_count)
164 {
165 col -= table->col_count;
166 table = table->next;
167 assert(table);
168 }
169
170 *table_col = col;
171 return table;
172}
173
175 UINT *column_type)
176{
177 struct join_table *table = wv->tables;
178 UINT i, r;
179
180 do
181 {
182 LPCWSTR table_name;
183
184 if (column->unparsed.table)
185 {
186 r = table->view->ops->get_column_info(table->view, 1, NULL, NULL,
187 NULL, &table_name);
188 if (r != ERROR_SUCCESS)
189 return r;
190 if (wcscmp(table_name, column->unparsed.table) != 0)
191 continue;
192 }
193
194 for(i = 1; i <= table->col_count; i++)
195 {
196 LPCWSTR col_name;
197
198 r = table->view->ops->get_column_info(table->view, i, &col_name, column_type,
199 NULL, NULL);
200 if(r != ERROR_SUCCESS )
201 return r;
202
203 if(wcscmp(col_name, column->unparsed.column))
204 continue;
205 column->parsed.column = i;
206 column->parsed.table = table;
207 return ERROR_SUCCESS;
208 }
209 }
210 while ((table = table->next));
211
212 WARN("Couldn't find column %s.%s\n", debugstr_w( column->unparsed.table ), debugstr_w( column->unparsed.column ) );
214}
215
217{
219 struct join_table *table;
220 UINT *rows;
221 UINT r;
222
223 TRACE("%p %d %d %p\n", wv, row, col, val );
224
225 if( !wv->tables )
227
228 r = find_row(wv, row, &rows);
229 if (r != ERROR_SUCCESS)
230 return r;
231
232 table = find_table(wv, col, &col);
233 if (!table)
235
236 return table->view->ops->fetch_int(table->view, rows[table->table_index], col, val);
237}
238
240{
242 struct join_table *table;
243 UINT *rows;
244 UINT r;
245
246 TRACE("%p %d %d %p\n", wv, row, col, stm );
247
248 if( !wv->tables )
250
251 r = find_row(wv, row, &rows);
252 if (r != ERROR_SUCCESS)
253 return r;
254
255 table = find_table(wv, col, &col);
256 if (!table)
258
259 return table->view->ops->fetch_stream( table->view, rows[table->table_index], col, stm );
260}
261
262static UINT WHERE_set_int(struct tagMSIVIEW *view, UINT row, UINT col, int val)
263{
265 struct join_table *table;
266 UINT *rows;
267 UINT r;
268
269 TRACE("view %p, row %u, col %u, val %d.\n", wv, row, col, val );
270
271 r = find_row(wv, row, &rows);
272 if (r != ERROR_SUCCESS)
273 return r;
274
275 table = find_table(wv, col, &col);
276 if (!table)
278
279 return table->view->ops->set_int(table->view, rows[table->table_index], col, val);
280}
281
282static UINT WHERE_set_string(struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
283{
285 struct join_table *table;
286 UINT *rows;
287 UINT r;
288
289 TRACE("view %p, row %u, col %u, val %s.\n", wv, row, col, debugstr_wn(val, len));
290
291 r = find_row(wv, row, &rows);
292 if (r != ERROR_SUCCESS)
293 return r;
294
295 table = find_table(wv, col, &col);
296 if (!table)
298
299 return table->view->ops->set_string(table->view, rows[table->table_index], col, val, len);
300}
301
303{
305 struct join_table *table;
306 UINT *rows;
307 UINT r;
308
309 TRACE("view %p, row %u, col %u, stream %p.\n", wv, row, col, stream);
310
311 r = find_row(wv, row, &rows);
312 if (r != ERROR_SUCCESS)
313 return r;
314
315 table = find_table(wv, col, &col);
316 if (!table)
318
319 return table->view->ops->set_stream(table->view, rows[table->table_index], col, stream);
320}
321
323{
325 UINT i, r, offset = 0;
326 struct join_table *table = wv->tables;
327 UINT *rows;
328 UINT mask_copy = mask;
329
330 TRACE("%p %d %p %08x\n", wv, row, rec, mask );
331
332 if( !wv->tables )
334
335 r = find_row(wv, row, &rows);
336 if (r != ERROR_SUCCESS)
337 return r;
338
339 if (mask >= 1 << wv->col_count)
341
342 do
343 {
344 for (i = 0; i < table->col_count; i++) {
345 UINT type;
346
347 if (!(mask_copy & (1 << i)))
348 continue;
349 r = table->view->ops->get_column_info(table->view, i + 1, NULL,
350 &type, NULL, NULL );
351 if (r != ERROR_SUCCESS)
352 return r;
353 if (type & MSITYPE_KEY)
355 }
356 mask_copy >>= table->col_count;
357 }
358 while (mask_copy && (table = table->next));
359
360 table = wv->tables;
361
362 do
363 {
364 const UINT col_count = table->col_count;
365 UINT i;
366 MSIRECORD *reduced;
367 UINT reduced_mask = (mask >> offset) & ((1 << col_count) - 1);
368
369 if (!reduced_mask)
370 {
371 offset += col_count;
372 continue;
373 }
374
375 reduced = MSI_CreateRecord(col_count);
376 if (!reduced)
378
379 for (i = 1; i <= col_count; i++)
380 {
381 r = MSI_RecordCopyField(rec, i + offset, reduced, i);
382 if (r != ERROR_SUCCESS)
383 break;
384 }
385
386 offset += col_count;
387
388 if (r == ERROR_SUCCESS)
389 r = table->view->ops->set_row(table->view, rows[table->table_index], reduced, reduced_mask);
390
391 msiobj_release(&reduced->hdr);
392 }
393 while ((table = table->next));
394 return r;
395}
396
398{
400 UINT r;
401 UINT *rows;
402
403 TRACE("(%p %d)\n", view, row);
404
405 if (!wv->tables)
407
408 r = find_row(wv, row, &rows);
409 if ( r != ERROR_SUCCESS )
410 return r;
411
412 if (wv->table_count > 1)
414
415 return wv->tables->view->ops->delete_row(wv->tables->view, rows[0]);
416}
417
418static INT INT_evaluate_binary( MSIWHEREVIEW *wv, const UINT rows[],
419 const struct complex_expr *expr, INT *val, MSIRECORD *record )
420{
421 UINT rl, rr;
422 INT lval, rval;
423
424 rl = WHERE_evaluate(wv, rows, expr->left, &lval, record);
425 if (rl != ERROR_SUCCESS && rl != ERROR_CONTINUE)
426 return rl;
427 rr = WHERE_evaluate(wv, rows, expr->right, &rval, record);
428 if (rr != ERROR_SUCCESS && rr != ERROR_CONTINUE)
429 return rr;
430
431 if (rl == ERROR_CONTINUE || rr == ERROR_CONTINUE)
432 {
433 if (rl == rr)
434 {
435 *val = TRUE;
436 return ERROR_CONTINUE;
437 }
438
439 if (expr->op == OP_AND)
440 {
441 if ((rl == ERROR_CONTINUE && !rval) || (rr == ERROR_CONTINUE && !lval))
442 {
443 *val = FALSE;
444 return ERROR_SUCCESS;
445 }
446 }
447 else if (expr->op == OP_OR)
448 {
449 if ((rl == ERROR_CONTINUE && rval) || (rr == ERROR_CONTINUE && lval))
450 {
451 *val = TRUE;
452 return ERROR_SUCCESS;
453 }
454 }
455
456 *val = TRUE;
457 return ERROR_CONTINUE;
458 }
459
460 switch( expr->op )
461 {
462 case OP_EQ:
463 *val = ( lval == rval );
464 break;
465 case OP_AND:
466 *val = ( lval && rval );
467 break;
468 case OP_OR:
469 *val = ( lval || rval );
470 break;
471 case OP_GT:
472 *val = ( lval > rval );
473 break;
474 case OP_LT:
475 *val = ( lval < rval );
476 break;
477 case OP_LE:
478 *val = ( lval <= rval );
479 break;
480 case OP_GE:
481 *val = ( lval >= rval );
482 break;
483 case OP_NE:
484 *val = ( lval != rval );
485 break;
486 default:
487 ERR("Unknown operator %d\n", expr->op );
489 }
490
491 return ERROR_SUCCESS;
492}
493
494static inline UINT expr_fetch_value(const union ext_column *expr, const UINT rows[], UINT *val)
495{
496 struct join_table *table = expr->parsed.table;
497
498 if( rows[table->table_index] == INVALID_ROW_INDEX )
499 {
500 *val = 1;
501 return ERROR_CONTINUE;
502 }
503 return table->view->ops->fetch_int(table->view, rows[table->table_index],
504 expr->parsed.column, val);
505}
506
507
508static UINT INT_evaluate_unary( MSIWHEREVIEW *wv, const UINT rows[],
509 const struct complex_expr *expr, INT *val, MSIRECORD *record )
510{
511 UINT r;
512 UINT lval;
513
514 r = expr_fetch_value(&expr->left->u.column, rows, &lval);
515 if(r != ERROR_SUCCESS)
516 return r;
517
518 switch( expr->op )
519 {
520 case OP_ISNULL:
521 *val = !lval;
522 break;
523 case OP_NOTNULL:
524 *val = lval;
525 break;
526 default:
527 ERR("Unknown operator %d\n", expr->op );
529 }
530 return ERROR_SUCCESS;
531}
532
533static UINT STRING_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
534 const struct expr *expr,
535 const MSIRECORD *record,
536 const WCHAR **str )
537{
538 UINT val = 0, r = ERROR_SUCCESS;
539
540 switch( expr->type )
541 {
543 r = expr_fetch_value(&expr->u.column, rows, &val);
544 if (r == ERROR_SUCCESS)
546 else
547 *str = NULL;
548 break;
549
550 case EXPR_SVAL:
551 *str = expr->u.sval;
552 break;
553
554 case EXPR_WILDCARD:
556 break;
557
558 default:
559 ERR("Invalid expression type\n");
561 *str = NULL;
562 break;
563 }
564 return r;
565}
566
567static UINT STRCMP_Evaluate( MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr,
568 INT *val, const MSIRECORD *record )
569{
570 int sr;
571 const WCHAR *l_str, *r_str;
572 UINT r;
573
574 *val = TRUE;
575 r = STRING_evaluate(wv, rows, expr->left, record, &l_str);
576 if (r == ERROR_CONTINUE)
577 return r;
578 r = STRING_evaluate(wv, rows, expr->right, record, &r_str);
579 if (r == ERROR_CONTINUE)
580 return r;
581
582 if( l_str == r_str ||
583 ((!l_str || !*l_str) && (!r_str || !*r_str)) )
584 sr = 0;
585 else if( l_str && ! r_str )
586 sr = 1;
587 else if( r_str && ! l_str )
588 sr = -1;
589 else
590 sr = wcscmp( l_str, r_str );
591
592 *val = ( expr->op == OP_EQ && ( sr == 0 ) ) ||
593 ( expr->op == OP_NE && ( sr != 0 ) );
594
595 return ERROR_SUCCESS;
596}
597
598static UINT WHERE_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
599 struct expr *cond, INT *val, MSIRECORD *record )
600{
601 UINT r, tval;
602
603 if( !cond )
604 {
605 *val = TRUE;
606 return ERROR_SUCCESS;
607 }
608
609 switch( cond->type )
610 {
611 case EXPR_COL_NUMBER:
612 r = expr_fetch_value(&cond->u.column, rows, &tval);
613 if( r != ERROR_SUCCESS )
614 return r;
615 *val = tval - 0x8000;
616 return ERROR_SUCCESS;
617
619 r = expr_fetch_value(&cond->u.column, rows, &tval);
620 if( r != ERROR_SUCCESS )
621 return r;
622 *val = tval - 0x80000000;
623 return r;
624
625 case EXPR_UVAL:
626 *val = cond->u.uval;
627 return ERROR_SUCCESS;
628
629 case EXPR_COMPLEX:
630 return INT_evaluate_binary(wv, rows, &cond->u.expr, val, record);
631
632 case EXPR_UNARY:
633 return INT_evaluate_unary( wv, rows, &cond->u.expr, val, record );
634
635 case EXPR_STRCMP:
636 return STRCMP_Evaluate( wv, rows, &cond->u.expr, val, record );
637
638 case EXPR_WILDCARD:
640 return ERROR_SUCCESS;
641
642 default:
643 ERR("Invalid expression type\n");
645 }
646
647 return ERROR_SUCCESS;
648}
649
651 UINT table_rows[] )
652{
654 INT val;
655
656 for (table_rows[(*tables)->table_index] = 0;
657 table_rows[(*tables)->table_index] < (*tables)->row_count;
658 table_rows[(*tables)->table_index]++)
659 {
660 val = 0;
661 wv->rec_index = 0;
662 r = WHERE_evaluate( wv, table_rows, wv->cond, &val, record );
663 if (r != ERROR_SUCCESS && r != ERROR_CONTINUE)
664 break;
665 if (val)
666 {
667 if (*(tables + 1))
668 {
669 r = check_condition(wv, record, tables + 1, table_rows);
670 if (r != ERROR_SUCCESS)
671 break;
672 }
673 else
674 {
675 if (r != ERROR_SUCCESS)
676 break;
677 add_row (wv, table_rows);
678 }
679 }
680 }
681 table_rows[(*tables)->table_index] = INVALID_ROW_INDEX;
682 return r;
683}
684
685static int __cdecl compare_entry( const void *left, const void *right )
686{
687 const struct row_entry *le = *(const struct row_entry **)left;
688 const struct row_entry *re = *(const struct row_entry **)right;
689 const MSIWHEREVIEW *wv = le->wv;
690 MSIORDERINFO *order = wv->order_info;
691 UINT i, j, r, l_val, r_val;
692
693 assert(le->wv == re->wv);
694
695 if (order)
696 {
697 for (i = 0; i < order->col_count; i++)
698 {
699 const union ext_column *column = &order->columns[i];
700
701 r = column->parsed.table->view->ops->fetch_int(column->parsed.table->view,
702 le->values[column->parsed.table->table_index],
703 column->parsed.column, &l_val);
704 if (r != ERROR_SUCCESS)
705 {
706 order->error = r;
707 return 0;
708 }
709
710 r = column->parsed.table->view->ops->fetch_int(column->parsed.table->view,
711 re->values[column->parsed.table->table_index],
712 column->parsed.column, &r_val);
713 if (r != ERROR_SUCCESS)
714 {
715 order->error = r;
716 return 0;
717 }
718
719 if (l_val != r_val)
720 return l_val < r_val ? -1 : 1;
721 }
722 }
723
724 for (j = 0; j < wv->table_count; j++)
725 {
726 if (le->values[j] != re->values[j])
727 return le->values[j] < re->values[j] ? -1 : 1;
728 }
729 return 0;
730}
731
732static void add_to_array( struct join_table **array, struct join_table *elem )
733{
734 while (*array && *array != elem)
735 array++;
736 if (!*array)
737 *array = elem;
738}
739
740static BOOL in_array( struct join_table **array, struct join_table *elem )
741{
742 while (*array && *array != elem)
743 array++;
744 return *array != NULL;
745}
746
747#define CONST_EXPR 1 /* comparison to a constant value */
748#define JOIN_TO_CONST_EXPR 0x10000 /* comparison to a table involved with
749 a CONST_EXPR comaprison */
751static UINT reorder_check( const struct expr *expr, struct join_table **ordered_tables,
752 BOOL process_joins, struct join_table **lastused )
753{
754 UINT res = 0;
755
756 switch (expr->type)
757 {
758 case EXPR_WILDCARD:
759 case EXPR_SVAL:
760 case EXPR_UVAL:
761 return 0;
762 case EXPR_COL_NUMBER:
765 if (in_array(ordered_tables, expr->u.column.parsed.table))
766 return JOIN_TO_CONST_EXPR;
767 *lastused = expr->u.column.parsed.table;
768 return CONST_EXPR;
769 case EXPR_STRCMP:
770 case EXPR_COMPLEX:
771 res = reorder_check(expr->u.expr.right, ordered_tables, process_joins, lastused);
772 /* fall through */
773 case EXPR_UNARY:
774 res += reorder_check(expr->u.expr.left, ordered_tables, process_joins, lastused);
775 if (res == 0)
776 return 0;
777 if (res == CONST_EXPR)
778 add_to_array(ordered_tables, *lastused);
779 if (process_joins && res == JOIN_TO_CONST_EXPR + CONST_EXPR)
780 add_to_array(ordered_tables, *lastused);
781 return res;
782 default:
783 ERR("Unknown expr type: %i\n", expr->type);
784 assert(0);
785 return 0x1000000;
786 }
787}
788
789/* reorders the tablelist in a way to evaluate the condition as fast as possible */
790static struct join_table **ordertables( MSIWHEREVIEW *wv )
791{
792 struct join_table *table, **tables;
793
794 tables = calloc(wv->table_count + 1, sizeof(*tables));
795
796 if (wv->cond)
797 {
798 table = NULL;
800 table = NULL;
802 }
803
804 table = wv->tables;
805 while (table)
806 {
808 table = table->next;
809 }
810 return tables;
811}
814{
816 UINT r;
817 struct join_table *table = wv->tables;
818 UINT *rows;
819 struct join_table **ordered_tables;
820 UINT i = 0;
821
822 TRACE("%p %p\n", wv, record);
823
824 if( !table )
826
827 r = init_reorder(wv);
828 if (r != ERROR_SUCCESS)
829 return r;
830
831 do
832 {
833 table->view->ops->execute(table->view, NULL);
834
835 r = table->view->ops->get_dimensions(table->view, &table->row_count, NULL);
836 if (r != ERROR_SUCCESS)
837 {
838 ERR("failed to get table dimensions\n");
839 return r;
840 }
841
842 /* each table must have at least one row */
843 if (table->row_count == 0)
844 return ERROR_SUCCESS;
845 }
846 while ((table = table->next));
847
848 ordered_tables = ordertables( wv );
849
850 rows = malloc(wv->table_count * sizeof(*rows));
851 for (i = 0; i < wv->table_count; i++)
852 rows[i] = INVALID_ROW_INDEX;
853
854 r = check_condition(wv, record, ordered_tables, rows);
855
856 if (wv->order_info)
858
859 qsort(wv->reorder, wv->row_count, sizeof(struct row_entry *), compare_entry);
860
861 if (wv->order_info)
862 r = wv->order_info->error;
863
864 free(rows);
865 free(ordered_tables);
866 return r;
867}
869static UINT WHERE_close( struct tagMSIVIEW *view )
870{
872 struct join_table *table = wv->tables;
873
874 TRACE("%p\n", wv );
875
876 if (!table)
878
879 do
880 table->view->ops->close(table->view);
881 while ((table = table->next));
882
883 return ERROR_SUCCESS;
884}
886static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
887{
889
890 TRACE("%p %p %p\n", wv, rows, cols );
891
892 if(!wv->tables)
894
895 if (rows)
896 {
897 if (!wv->reorder)
899 *rows = wv->row_count;
900 }
901
902 if (cols)
903 *cols = wv->col_count;
904
905 return ERROR_SUCCESS;
906}
909 UINT *type, BOOL *temporary, LPCWSTR *table_name )
910{
912 struct join_table *table;
913
914 TRACE("%p %d %p %p %p %p\n", wv, n, name, type, temporary, table_name );
915
916 if(!wv->tables)
918
919 table = find_table(wv, n, &n);
920 if (!table)
922
923 return table->view->ops->get_column_info(table->view, n, name,
924 type, temporary, table_name);
925}
927static UINT join_find_row( MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row )
928{
929 LPCWSTR str;
930 UINT r, i, id, data;
931
932 str = MSI_RecordGetString( rec, 1 );
933 r = msi_string2id( wv->db->strings, str, -1, &id );
934 if (r != ERROR_SUCCESS)
935 return r;
936
937 for (i = 0; i < wv->row_count; i++)
938 {
939 WHERE_fetch_int( &wv->view, i, 1, &data );
940
941 if (data == id)
942 {
943 *row = i;
944 return ERROR_SUCCESS;
945 }
946 }
947
949}
951static UINT join_modify_update( struct tagMSIVIEW *view, MSIRECORD *rec )
952{
954 UINT r, row, i, mask = 0;
956
957
958 r = join_find_row( wv, rec, &row );
959 if (r != ERROR_SUCCESS)
960 return r;
961
962 r = msi_view_get_row( wv->db, view, row, &current );
963 if (r != ERROR_SUCCESS)
964 return r;
965
967
968 for (i = MSI_RecordGetFieldCount(rec); i > 0; i--)
969 {
971 mask |= 1 << (i - 1);
972 }
973 msiobj_release(&current->hdr);
974
975 return WHERE_set_row( view, row, rec, mask );
976}
978static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
979 MSIRECORD *rec, UINT row )
980{
982 struct join_table *table = wv->tables;
983 UINT r;
984
985 TRACE("%p %d %p\n", wv, eModifyMode, rec);
986
987 if (!table)
989
990 if (!table->next)
991 {
992 UINT *rows;
993
994 if (find_row(wv, row, &rows) == ERROR_SUCCESS)
995 row = rows[0];
996 else
997 row = -1;
998
999 return table->view->ops->modify(table->view, eModifyMode, rec, row);
1000 }
1001
1002 switch (eModifyMode)
1003 {
1004 case MSIMODIFY_UPDATE:
1005 return join_modify_update( view, rec );
1006
1007 case MSIMODIFY_ASSIGN:
1008 case MSIMODIFY_DELETE:
1009 case MSIMODIFY_INSERT:
1011 case MSIMODIFY_MERGE:
1012 case MSIMODIFY_REPLACE:
1013 case MSIMODIFY_SEEK:
1014 case MSIMODIFY_VALIDATE:
1019 break;
1020
1021 case MSIMODIFY_REFRESH:
1023 break;
1024
1025 default:
1026 WARN("%p %d %p %u - unknown mode\n", view, eModifyMode, rec, row );
1028 break;
1029 }
1030
1031 return r;
1032}
1034static UINT WHERE_delete( struct tagMSIVIEW *view )
1035{
1037 struct join_table *table = wv->tables;
1038
1039 TRACE("%p\n", wv );
1040
1041 while(table)
1042 {
1043 struct join_table *next;
1044
1045 table->view->ops->delete(table->view);
1046 table->view = NULL;
1047 next = table->next;
1048 free(table);
1049 table = next;
1050 }
1051 wv->tables = NULL;
1052 wv->table_count = 0;
1053
1054 free_reorder(wv);
1055
1056 free(wv->order_info);
1057 wv->order_info = NULL;
1058
1059 msiobj_release( &wv->db->hdr );
1060 free(wv);
1061
1062 return ERROR_SUCCESS;
1063}
1065static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns)
1066{
1068 struct join_table *table = wv->tables;
1069 column_info *column = columns;
1070 MSIORDERINFO *orderinfo;
1071 UINT r, count = 0;
1072 UINT i;
1073
1074 TRACE("%p %p\n", view, columns);
1075
1076 if (!table)
1077 return ERROR_FUNCTION_FAILED;
1078
1079 while (column)
1080 {
1081 count++;
1082 column = column->next;
1083 }
1084
1085 if (count == 0)
1086 return ERROR_SUCCESS;
1087
1088 orderinfo = malloc(offsetof(MSIORDERINFO, columns[count]));
1089 if (!orderinfo)
1090 return ERROR_OUTOFMEMORY;
1091
1092 orderinfo->col_count = count;
1093
1094 column = columns;
1095
1096 for (i = 0; i < count; i++)
1097 {
1098 orderinfo->columns[i].unparsed.column = column->column;
1099 orderinfo->columns[i].unparsed.table = column->table;
1100
1101 r = parse_column(wv, &orderinfo->columns[i], NULL);
1102 if (r != ERROR_SUCCESS)
1103 goto error;
1104 }
1105
1106 wv->order_info = orderinfo;
1107
1108 return ERROR_SUCCESS;
1109error:
1110 free(orderinfo);
1111 return r;
1112}
1114static const MSIVIEWOPS where_ops =
1115{
1122 NULL,
1130 NULL,
1131 NULL,
1132 NULL,
1133 WHERE_sort,
1134 NULL,
1135};
1137static UINT WHERE_VerifyCondition( MSIWHEREVIEW *wv, struct expr *cond,
1138 UINT *valid )
1139{
1140 UINT r;
1141
1142 switch( cond->type )
1143 {
1144 case EXPR_COLUMN:
1145 {
1146 UINT type;
1147
1148 *valid = FALSE;
1149
1150 r = parse_column(wv, &cond->u.column, &type);
1151 if (r != ERROR_SUCCESS)
1152 break;
1153
1154 if (type&MSITYPE_STRING)
1156 else if ((type&0xff) == 4)
1157 cond->type = EXPR_COL_NUMBER32;
1158 else
1159 cond->type = EXPR_COL_NUMBER;
1160
1161 *valid = TRUE;
1162 break;
1163 }
1164 case EXPR_COMPLEX:
1165 r = WHERE_VerifyCondition( wv, cond->u.expr.left, valid );
1166 if( r != ERROR_SUCCESS )
1167 return r;
1168 if( !*valid )
1169 return ERROR_SUCCESS;
1170 r = WHERE_VerifyCondition( wv, cond->u.expr.right, valid );
1171 if( r != ERROR_SUCCESS )
1172 return r;
1173
1174 /* check the type of the comparison */
1175 if( ( cond->u.expr.left->type == EXPR_SVAL ) ||
1176 ( cond->u.expr.left->type == EXPR_COL_NUMBER_STRING ) ||
1177 ( cond->u.expr.right->type == EXPR_SVAL ) ||
1178 ( cond->u.expr.right->type == EXPR_COL_NUMBER_STRING ) )
1179 {
1180 switch( cond->u.expr.op )
1181 {
1182 case OP_EQ:
1183 case OP_NE:
1184 break;
1185 default:
1186 *valid = FALSE;
1188 }
1189
1190 /* FIXME: check we're comparing a string to a column */
1191
1192 cond->type = EXPR_STRCMP;
1193 }
1194
1195 break;
1196 case EXPR_UNARY:
1197 if ( cond->u.expr.left->type != EXPR_COLUMN )
1198 {
1199 *valid = FALSE;
1201 }
1202 r = WHERE_VerifyCondition( wv, cond->u.expr.left, valid );
1203 if( r != ERROR_SUCCESS )
1204 return r;
1205 break;
1206 case EXPR_IVAL:
1207 *valid = 1;
1208 cond->type = EXPR_UVAL;
1209 cond->u.uval = cond->u.ival;
1210 break;
1211 case EXPR_WILDCARD:
1212 *valid = 1;
1213 break;
1214 case EXPR_SVAL:
1215 *valid = 1;
1216 break;
1217 default:
1218 ERR("Invalid expression type\n");
1219 *valid = 0;
1220 break;
1221 }
1222
1223 return ERROR_SUCCESS;
1224}
1227 struct expr *cond )
1228{
1229 MSIWHEREVIEW *wv = NULL;
1230 UINT r, valid = 0;
1231 WCHAR *ptr;
1232
1233 TRACE("(%s)\n", debugstr_w(tables) );
1234
1235 wv = calloc(1, sizeof *wv);
1236 if( !wv )
1237 return ERROR_FUNCTION_FAILED;
1238
1239 /* fill the structure */
1240 wv->view.ops = &where_ops;
1241 msiobj_addref( &db->hdr );
1242 wv->db = db;
1243 wv->cond = cond;
1244
1245 while (*tables)
1246 {
1247 struct join_table *table;
1248
1249 if ((ptr = wcschr(tables, ' ')))
1250 *ptr = '\0';
1251
1252 table = malloc(sizeof(*table));
1253 if (!table)
1254 {
1256 goto end;
1257 }
1258
1259 r = TABLE_CreateView(db, tables, &table->view);
1260 if (r != ERROR_SUCCESS)
1261 {
1262 WARN("can't create table: %s\n", debugstr_w(tables));
1263 free(table);
1265 goto end;
1266 }
1267
1268 r = table->view->ops->get_dimensions(table->view, NULL,
1269 &table->col_count);
1270 if (r != ERROR_SUCCESS)
1271 {
1272 ERR("can't get table dimensions\n");
1273 table->view->ops->delete(table->view);
1274 free(table);
1275 goto end;
1276 }
1277
1278 wv->col_count += table->col_count;
1279 table->table_index = wv->table_count++;
1280
1281 table->next = wv->tables;
1282 wv->tables = table;
1283
1284 if (!ptr)
1285 break;
1286
1287 tables = ptr + 1;
1288 }
1289
1290 if( cond )
1291 {
1292 r = WHERE_VerifyCondition( wv, cond, &valid );
1293 if( r != ERROR_SUCCESS )
1294 goto end;
1295 if( !valid ) {
1297 goto end;
1298 }
1299 }
1300
1301 *view = (MSIVIEW*) wv;
1302
1303 return ERROR_SUCCESS;
1304end:
1305 WHERE_delete(&wv->view);
1306
1307 return r;
1308}
#define __cdecl
Definition: accygwin.h:79
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
float rval
Definition: cylfrac.c:48
#define ERROR_CONTINUE
Definition: dderror.h:17
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define wcschr
Definition: compat.h:17
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
void msiobj_addref(MSIOBJECTHDR *info)
Definition: handle.c:217
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
static UINT WHERE_close(struct tagMSIVIEW *view)
Definition: where.c:868
static UINT add_row(MSIWHEREVIEW *wv, UINT vals[])
Definition: where.c:125
#define INITIAL_REORDER_SIZE
Definition: where.c:81
static UINT WHERE_set_string(struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
Definition: where.c:282
#define JOIN_TO_CONST_EXPR
Definition: where.c:748
static UINT expr_fetch_value(const union ext_column *expr, const UINT rows[], UINT *val)
Definition: where.c:494
static UINT WHERE_execute(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: where.c:812
static UINT WHERE_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: where.c:322
static void free_reorder(MSIWHEREVIEW *wv)
Definition: where.c:85
static INT INT_evaluate_binary(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, MSIRECORD *record)
Definition: where.c:418
static UINT WHERE_delete_row(struct tagMSIVIEW *view, UINT row)
Definition: where.c:397
static struct join_table ** ordertables(MSIWHEREVIEW *wv)
Definition: where.c:789
struct tagMSIORDERINFO MSIORDERINFO
static UINT check_condition(MSIWHEREVIEW *wv, MSIRECORD *record, struct join_table **tables, UINT table_rows[])
Definition: where.c:650
#define CONST_EXPR
Definition: where.c:747
static UINT WHERE_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: where.c:885
static UINT STRING_evaluate(MSIWHEREVIEW *wv, const UINT rows[], const struct expr *expr, const MSIRECORD *record, const WCHAR **str)
Definition: where.c:533
static UINT INT_evaluate_unary(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, MSIRECORD *record)
Definition: where.c:508
struct tagMSIWHEREVIEW MSIWHEREVIEW
static void add_to_array(struct join_table **array, struct join_table *elem)
Definition: where.c:732
static UINT join_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec)
Definition: where.c:950
static struct join_table * find_table(MSIWHEREVIEW *wv, UINT col, UINT *table_col)
Definition: where.c:156
static UINT WHERE_set_int(struct tagMSIVIEW *view, UINT row, UINT col, int val)
Definition: where.c:262
static UINT WHERE_get_column_info(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: where.c:907
static int __cdecl compare_entry(const void *left, const void *right)
Definition: where.c:685
static UINT reorder_check(const struct expr *expr, struct join_table **ordered_tables, BOOL process_joins, struct join_table **lastused)
Definition: where.c:750
static UINT STRCMP_Evaluate(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, const MSIRECORD *record)
Definition: where.c:567
#define INVALID_ROW_INDEX
Definition: where.c:83
static UINT WHERE_VerifyCondition(MSIWHEREVIEW *wv, struct expr *cond, UINT *valid)
Definition: where.c:1136
static UINT WHERE_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: where.c:216
static UINT WHERE_evaluate(MSIWHEREVIEW *wv, const UINT rows[], struct expr *cond, INT *val, MSIRECORD *record)
Definition: where.c:598
static UINT find_row(MSIWHEREVIEW *wv, UINT row, UINT *(values[]))
Definition: where.c:115
static UINT parse_column(MSIWHEREVIEW *wv, union ext_column *column, UINT *column_type)
Definition: where.c:174
static BOOL in_array(struct join_table **array, struct join_table *elem)
Definition: where.c:740
static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns)
Definition: where.c:1064
static UINT init_reorder(MSIWHEREVIEW *wv)
Definition: where.c:101
static UINT WHERE_delete(struct tagMSIVIEW *view)
Definition: where.c:1033
static const MSIVIEWOPS where_ops
Definition: where.c:1113
UINT WHERE_CreateView(MSIDATABASE *db, MSIVIEW **view, LPWSTR tables, struct expr *cond)
Definition: where.c:1225
static UINT WHERE_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
Definition: where.c:977
static UINT join_find_row(MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row)
Definition: where.c:926
static UINT WHERE_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: where.c:239
static UINT WHERE_set_stream(MSIVIEW *view, UINT row, UINT col, IStream *stream)
Definition: where.c:302
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
#define assert(x)
Definition: debug.h:53
struct nls_table * tables
Definition: nls_base.c:22
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOLEAN valid
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLenum GLint GLuint mask
Definition: glext.h:6028
GLdouble GLdouble right
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLuint GLfloat * val
Definition: glext.h:7180
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct task_struct * current
Definition: linux.c:32
static PVOID ptr
Definition: dispmode.c:27
static size_t elem
Definition: string.c:68
int MSI_RecordGetInteger(MSIRECORD *, UINT)
Definition: record.c:213
UINT msi_string2id(const string_table *st, const WCHAR *data, int len, UINT *id)
Definition: string.c:400
#define MSITYPE_STRING
Definition: msipriv.h:50
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT)
Definition: record.c:433
UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **)
Definition: msiquery.c:353
BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field)
Definition: record.c:957
const WCHAR * msi_string_lookup(const string_table *st, UINT id, int *len)
Definition: string.c:343
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT)
Definition: record.c:166
#define MSITYPE_KEY
Definition: msipriv.h:52
MSIRECORD * MSI_CreateRecord(UINT)
Definition: record.c:76
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec)
Definition: record.c:108
@ MSIMODIFY_DELETE
Definition: msiquery.h:57
@ MSIMODIFY_REPLACE
Definition: msiquery.h:55
@ MSIMODIFY_MERGE
Definition: msiquery.h:56
@ MSIMODIFY_INSERT_TEMPORARY
Definition: msiquery.h:58
@ MSIMODIFY_UPDATE
Definition: msiquery.h:53
@ MSIMODIFY_VALIDATE_DELETE
Definition: msiquery.h:62
@ MSIMODIFY_SEEK
Definition: msiquery.h:50
@ MSIMODIFY_ASSIGN
Definition: msiquery.h:54
@ MSIMODIFY_VALIDATE_NEW
Definition: msiquery.h:60
@ MSIMODIFY_INSERT
Definition: msiquery.h:52
@ MSIMODIFY_REFRESH
Definition: msiquery.h:51
@ MSIMODIFY_VALIDATE_FIELD
Definition: msiquery.h:61
@ MSIMODIFY_VALIDATE
Definition: msiquery.h:59
unsigned int UINT
Definition: ndis.h:50
#define EXPR_COL_NUMBER32
Definition: query.h:56
#define OP_LT
Definition: query.h:40
#define OP_GT
Definition: query.h:39
#define EXPR_STRCMP
Definition: query.h:53
#define EXPR_COMPLEX
Definition: query.h:47
#define EXPR_WILDCARD
Definition: query.h:54
#define OP_EQ
Definition: query.h:36
#define OP_NOTNULL
Definition: query.h:45
#define EXPR_COL_NUMBER
Definition: query.h:49
#define EXPR_IVAL
Definition: query.h:50
#define OP_GE
Definition: query.h:42
#define EXPR_COL_NUMBER_STRING
Definition: query.h:55
#define OP_ISNULL
Definition: query.h:44
#define EXPR_COLUMN
Definition: query.h:48
#define EXPR_UNARY
Definition: query.h:57
#define OP_AND
Definition: query.h:37
#define EXPR_SVAL
Definition: query.h:51
#define OP_NE
Definition: query.h:43
#define EXPR_UVAL
Definition: query.h:52
#define OP_OR
Definition: query.h:38
UINT TABLE_CreateView(MSIDATABASE *db, LPCWSTR name, MSIVIEW **view)
Definition: table.c:2191
#define OP_LE
Definition: query.h:41
static unsigned __int64 next
Definition: rand_nt.c:6
#define calloc
Definition: rosglue.h:14
const WCHAR * str
#define offsetof(TYPE, MEMBER)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define memset(x, y, z)
Definition: compat.h:39
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
#define TRACE(s)
Definition: solgame.cpp:4
Definition: query.h:86
struct complex_expr expr
Definition: query.h:90
UINT uval
Definition: query.h:92
union ext_column column
Definition: query.h:94
union expr::@507 u
int type
Definition: query.h:87
LPCWSTR sval
Definition: query.h:93
INT ival
Definition: query.h:91
UINT col_count
Definition: where.c:51
UINT table_index
Definition: where.c:53
UINT row_count
Definition: where.c:52
MSIVIEW * view
Definition: where.c:50
struct join_table * next
Definition: where.c:49
Definition: name.c:39
Definition: where.c:42
struct tagMSIWHEREVIEW * wv
Definition: where.c:43
UINT values[1]
Definition: where.c:44
Definition: parse.h:23
MSIOBJECTHDR hdr
Definition: msipriv.h:108
string_table * strings
Definition: msipriv.h:110
union ext_column columns[1]
Definition: where.c:60
UINT error
Definition: where.c:59
UINT col_count
Definition: where.c:58
MSIOBJECTHDR hdr
Definition: msipriv.h:151
const MSIVIEWOPS * ops
Definition: msipriv.h:355
UINT reorder_size
Definition: where.c:72
struct expr * cond
Definition: where.c:73
struct join_table * tables
Definition: where.c:67
UINT table_count
Definition: where.c:70
struct row_entry ** reorder
Definition: where.c:71
MSIVIEW view
Definition: where.c:65
UINT row_count
Definition: where.c:68
MSIDATABASE * db
Definition: where.c:66
MSIORDERINFO * order_info
Definition: where.c:75
UINT col_count
Definition: where.c:69
UINT rec_index
Definition: where.c:74
#define new(TYPE, numElems)
Definition: treelist.c:54
int32_t INT
Definition: typedefs.h:58
struct ext_column::@506 parsed
struct ext_column::@505 unparsed
int MSIMODIFY
Definition: winemsi.idl:33
#define ERROR_BAD_QUERY_SYNTAX
Definition: winerror.h:973
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185