ReactOS  0.4.15-dev-5112-g22d8c0f
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 */
41 typedef struct tagMSIROWENTRY
42 {
43  struct tagMSIWHEREVIEW *wv; /* used during sorting */
45 } MSIROWENTRY;
46 
47 typedef struct tagJOINTABLE
48 {
49  struct tagJOINTABLE *next;
54 } JOINTABLE;
55 
56 typedef struct tagMSIORDERINFO
57 {
60  union ext_column columns[1];
61 } MSIORDERINFO;
62 
63 typedef struct tagMSIWHEREVIEW
64 {
72  UINT reorder_size; /* number of entries available in reorder */
73  struct expr *cond;
76 } MSIWHEREVIEW;
77 
78 static 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 
85 static 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  msi_free(wv->reorder[i]);
94 
95  msi_free( wv->reorder );
96  wv->reorder = NULL;
97  wv->reorder_size = 0;
98  wv->row_count = 0;
99 }
100 
102 {
104  if (!new)
105  return ERROR_OUTOFMEMORY;
106 
107  free_reorder(wv);
108 
109  wv->reorder = new;
111 
112  return ERROR_SUCCESS;
113 }
114 
115 static inline UINT find_row(MSIWHEREVIEW *wv, UINT row, UINT *(values[]))
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 
125 static UINT add_row(MSIWHEREVIEW *wv, UINT vals[])
126 {
127  MSIROWENTRY *new;
128 
129  if (wv->reorder_size <= wv->row_count)
130  {
131  MSIROWENTRY **new_reorder;
132  UINT newsize = wv->reorder_size * 2;
133 
134  new_reorder = msi_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 
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 
156 static JOINTABLE *find_table(MSIWHEREVIEW *wv, UINT col, UINT *table_col)
157 {
158  JOINTABLE *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  JOINTABLE *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 ) );
213  return ERROR_BAD_QUERY_SYNTAX;
214 }
215 
217 {
219  JOINTABLE *table;
220  UINT *rows;
221  UINT r;
222 
223  TRACE("%p %d %d %p\n", wv, row, col, val );
224 
225  if( !wv->tables )
226  return ERROR_FUNCTION_FAILED;
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)
234  return ERROR_FUNCTION_FAILED;
235 
236  return table->view->ops->fetch_int(table->view, rows[table->table_index], col, val);
237 }
238 
239 static UINT WHERE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm )
240 {
242  JOINTABLE *table;
243  UINT *rows;
244  UINT r;
245 
246  TRACE("%p %d %d %p\n", wv, row, col, stm );
247 
248  if( !wv->tables )
249  return ERROR_FUNCTION_FAILED;
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)
257  return ERROR_FUNCTION_FAILED;
258 
259  return table->view->ops->fetch_stream( table->view, rows[table->table_index], col, stm );
260 }
261 
262 static UINT WHERE_set_int(struct tagMSIVIEW *view, UINT row, UINT col, int val)
263 {
265  JOINTABLE *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)
277  return ERROR_FUNCTION_FAILED;
278 
279  return table->view->ops->set_int(table->view, rows[table->table_index], col, val);
280 }
281 
282 static UINT WHERE_set_string(struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
283 {
285  JOINTABLE *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)
297  return ERROR_FUNCTION_FAILED;
298 
299  return table->view->ops->set_string(table->view, rows[table->table_index], col, val, len);
300 }
301 
303 {
305  JOINTABLE *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)
317  return ERROR_FUNCTION_FAILED;
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  JOINTABLE *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 )
333  return ERROR_FUNCTION_FAILED;
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)
354  return ERROR_FUNCTION_FAILED;
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)
377  return ERROR_FUNCTION_FAILED;
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 {
399  MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
400  UINT r;
401  UINT *rows;
402 
403  TRACE("(%p %d)\n", view, row);
404 
405  if (!wv->tables)
406  return ERROR_FUNCTION_FAILED;
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 
418 static 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 );
488  return ERROR_FUNCTION_FAILED;
489  }
490 
491  return ERROR_SUCCESS;
492 }
493 
494 static inline UINT expr_fetch_value(const union ext_column *expr, const UINT rows[], UINT *val)
495 {
496  JOINTABLE *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 
508 static 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 );
528  return ERROR_FUNCTION_FAILED;
529  }
530  return ERROR_SUCCESS;
531 }
532 
533 static 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)
545  *str = msi_string_lookup(wv->db->strings, val, NULL);
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 
567 static 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 
598 static 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 
618  case EXPR_COL_NUMBER32:
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");
644  return ERROR_FUNCTION_FAILED;
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 
685 static int __cdecl compare_entry( const void *left, const void *right )
686 {
687  const MSIROWENTRY *le = *(const MSIROWENTRY**)left;
688  const MSIROWENTRY *re = *(const MSIROWENTRY**)right;
689  const MSIWHEREVIEW *wv = le->wv;
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 
733 {
734  while (*array && *array != elem)
735  array++;
736  if (!*array)
737  *array = elem;
738 }
739 
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 */
750 
751 static UINT reorder_check( const struct expr *expr, JOINTABLE **ordered_tables,
752  BOOL process_joins, JOINTABLE **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:
763  case EXPR_COL_NUMBER32:
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 */
791 {
792  JOINTABLE *table;
793  JOINTABLE **tables;
794 
795  tables = msi_alloc_zero( (wv->table_count + 1) * sizeof(*tables) );
796 
797  if (wv->cond)
798  {
799  table = NULL;
801  table = NULL;
803  }
804 
805  table = wv->tables;
806  while (table)
807  {
809  table = table->next;
810  }
811  return tables;
812 }
813 
815 {
817  UINT r;
818  JOINTABLE *table = wv->tables;
819  UINT *rows;
820  JOINTABLE **ordered_tables;
821  UINT i = 0;
822 
823  TRACE("%p %p\n", wv, record);
824 
825  if( !table )
826  return ERROR_FUNCTION_FAILED;
827 
828  r = init_reorder(wv);
829  if (r != ERROR_SUCCESS)
830  return r;
831 
832  do
833  {
834  table->view->ops->execute(table->view, NULL);
835 
836  r = table->view->ops->get_dimensions(table->view, &table->row_count, NULL);
837  if (r != ERROR_SUCCESS)
838  {
839  ERR("failed to get table dimensions\n");
840  return r;
841  }
842 
843  /* each table must have at least one row */
844  if (table->row_count == 0)
845  return ERROR_SUCCESS;
846  }
847  while ((table = table->next));
848 
849  ordered_tables = ordertables( wv );
850 
851  rows = msi_alloc( wv->table_count * sizeof(*rows) );
852  for (i = 0; i < wv->table_count; i++)
853  rows[i] = INVALID_ROW_INDEX;
854 
855  r = check_condition(wv, record, ordered_tables, rows);
856 
857  if (wv->order_info)
859 
860  qsort(wv->reorder, wv->row_count, sizeof(MSIROWENTRY *), compare_entry);
861 
862  if (wv->order_info)
863  r = wv->order_info->error;
864 
865  msi_free( rows );
866  msi_free( ordered_tables );
867  return r;
868 }
869 
870 static UINT WHERE_close( struct tagMSIVIEW *view )
871 {
873  JOINTABLE *table = wv->tables;
874 
875  TRACE("%p\n", wv );
876 
877  if (!table)
878  return ERROR_FUNCTION_FAILED;
879 
880  do
881  table->view->ops->close(table->view);
882  while ((table = table->next));
883 
884  return ERROR_SUCCESS;
885 }
886 
887 static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
888 {
890 
891  TRACE("%p %p %p\n", wv, rows, cols );
892 
893  if(!wv->tables)
894  return ERROR_FUNCTION_FAILED;
895 
896  if (rows)
897  {
898  if (!wv->reorder)
899  return ERROR_FUNCTION_FAILED;
900  *rows = wv->row_count;
901  }
902 
903  if (cols)
904  *cols = wv->col_count;
905 
906  return ERROR_SUCCESS;
907 }
908 
910  UINT *type, BOOL *temporary, LPCWSTR *table_name )
911 {
913  JOINTABLE *table;
914 
915  TRACE("%p %d %p %p %p %p\n", wv, n, name, type, temporary, table_name );
916 
917  if(!wv->tables)
918  return ERROR_FUNCTION_FAILED;
919 
920  table = find_table(wv, n, &n);
921  if (!table)
922  return ERROR_FUNCTION_FAILED;
923 
924  return table->view->ops->get_column_info(table->view, n, name,
925  type, temporary, table_name);
926 }
927 
929 {
930  LPCWSTR str;
931  UINT r, i, id, data;
932 
933  str = MSI_RecordGetString( rec, 1 );
934  r = msi_string2id( wv->db->strings, str, -1, &id );
935  if (r != ERROR_SUCCESS)
936  return r;
937 
938  for (i = 0; i < wv->row_count; i++)
939  {
940  WHERE_fetch_int( &wv->view, i, 1, &data );
941 
942  if (data == id)
943  {
944  *row = i;
945  return ERROR_SUCCESS;
946  }
947  }
948 
949  return ERROR_FUNCTION_FAILED;
950 }
951 
953 {
954  MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
955  UINT r, row, i, mask = 0;
957 
958 
959  r = join_find_row( wv, rec, &row );
960  if (r != ERROR_SUCCESS)
961  return r;
962 
963  r = msi_view_get_row( wv->db, view, row, &current );
964  if (r != ERROR_SUCCESS)
965  return r;
966 
968 
969  for (i = MSI_RecordGetFieldCount(rec); i > 0; i--)
970  {
971  if (!MSI_RecordsAreFieldsEqual(rec, current, i))
972  mask |= 1 << (i - 1);
973  }
974  msiobj_release(&current->hdr);
975 
976  return WHERE_set_row( view, row, rec, mask );
977 }
978 
979 static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
980  MSIRECORD *rec, UINT row )
981 {
983  JOINTABLE *table = wv->tables;
984  UINT r;
985 
986  TRACE("%p %d %p\n", wv, eModifyMode, rec);
987 
988  if (!table)
989  return ERROR_FUNCTION_FAILED;
990 
991  if (!table->next)
992  {
993  UINT *rows;
994 
995  if (find_row(wv, row, &rows) == ERROR_SUCCESS)
996  row = rows[0];
997  else
998  row = -1;
999 
1000  return table->view->ops->modify(table->view, eModifyMode, rec, row);
1001  }
1002 
1003  switch (eModifyMode)
1004  {
1005  case MSIMODIFY_UPDATE:
1006  return join_modify_update( view, rec );
1007 
1008  case MSIMODIFY_ASSIGN:
1009  case MSIMODIFY_DELETE:
1010  case MSIMODIFY_INSERT:
1012  case MSIMODIFY_MERGE:
1013  case MSIMODIFY_REPLACE:
1014  case MSIMODIFY_SEEK:
1015  case MSIMODIFY_VALIDATE:
1020  break;
1021 
1022  case MSIMODIFY_REFRESH:
1024  break;
1025 
1026  default:
1027  WARN("%p %d %p %u - unknown mode\n", view, eModifyMode, rec, row );
1029  break;
1030  }
1031 
1032  return r;
1033 }
1034 
1036 {
1037  MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
1038  JOINTABLE *table = wv->tables;
1039 
1040  TRACE("%p\n", wv );
1041 
1042  while(table)
1043  {
1044  JOINTABLE *next;
1045 
1046  table->view->ops->delete(table->view);
1047  table->view = NULL;
1048  next = table->next;
1049  msi_free(table);
1050  table = next;
1051  }
1052  wv->tables = NULL;
1053  wv->table_count = 0;
1054 
1055  free_reorder(wv);
1056 
1057  msi_free(wv->order_info);
1058  wv->order_info = NULL;
1059 
1060  msiobj_release( &wv->db->hdr );
1061  msi_free( wv );
1062 
1063  return ERROR_SUCCESS;
1064 }
1065 
1066 static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns)
1067 {
1068  MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
1069  JOINTABLE *table = wv->tables;
1070  column_info *column = columns;
1071  MSIORDERINFO *orderinfo;
1072  UINT r, count = 0;
1073  UINT i;
1074 
1075  TRACE("%p %p\n", view, columns);
1076 
1077  if (!table)
1078  return ERROR_FUNCTION_FAILED;
1079 
1080  while (column)
1081  {
1082  count++;
1083  column = column->next;
1084  }
1085 
1086  if (count == 0)
1087  return ERROR_SUCCESS;
1088 
1089  orderinfo = msi_alloc(FIELD_OFFSET(MSIORDERINFO, columns[count]));
1090  if (!orderinfo)
1091  return ERROR_OUTOFMEMORY;
1092 
1093  orderinfo->col_count = count;
1094 
1095  column = columns;
1096 
1097  for (i = 0; i < count; i++)
1098  {
1099  orderinfo->columns[i].unparsed.column = column->column;
1100  orderinfo->columns[i].unparsed.table = column->table;
1101 
1102  r = parse_column(wv, &orderinfo->columns[i], NULL);
1103  if (r != ERROR_SUCCESS)
1104  goto error;
1105  }
1106 
1107  wv->order_info = orderinfo;
1108 
1109  return ERROR_SUCCESS;
1110 error:
1111  msi_free(orderinfo);
1112  return r;
1113 }
1114 
1115 static const MSIVIEWOPS where_ops =
1116 {
1119  WHERE_set_int,
1122  WHERE_set_row,
1123  NULL,
1125  WHERE_execute,
1126  WHERE_close,
1129  WHERE_modify,
1130  WHERE_delete,
1131  NULL,
1132  NULL,
1133  NULL,
1134  WHERE_sort,
1135  NULL,
1136 };
1137 
1138 static UINT WHERE_VerifyCondition( MSIWHEREVIEW *wv, struct expr *cond,
1139  UINT *valid )
1140 {
1141  UINT r;
1142 
1143  switch( cond->type )
1144  {
1145  case EXPR_COLUMN:
1146  {
1147  UINT type;
1148 
1149  *valid = FALSE;
1150 
1151  r = parse_column(wv, &cond->u.column, &type);
1152  if (r != ERROR_SUCCESS)
1153  break;
1154 
1155  if (type&MSITYPE_STRING)
1156  cond->type = EXPR_COL_NUMBER_STRING;
1157  else if ((type&0xff) == 4)
1158  cond->type = EXPR_COL_NUMBER32;
1159  else
1160  cond->type = EXPR_COL_NUMBER;
1161 
1162  *valid = TRUE;
1163  break;
1164  }
1165  case EXPR_COMPLEX:
1166  r = WHERE_VerifyCondition( wv, cond->u.expr.left, valid );
1167  if( r != ERROR_SUCCESS )
1168  return r;
1169  if( !*valid )
1170  return ERROR_SUCCESS;
1171  r = WHERE_VerifyCondition( wv, cond->u.expr.right, valid );
1172  if( r != ERROR_SUCCESS )
1173  return r;
1174 
1175  /* check the type of the comparison */
1176  if( ( cond->u.expr.left->type == EXPR_SVAL ) ||
1177  ( cond->u.expr.left->type == EXPR_COL_NUMBER_STRING ) ||
1178  ( cond->u.expr.right->type == EXPR_SVAL ) ||
1179  ( cond->u.expr.right->type == EXPR_COL_NUMBER_STRING ) )
1180  {
1181  switch( cond->u.expr.op )
1182  {
1183  case OP_EQ:
1184  case OP_NE:
1185  break;
1186  default:
1187  *valid = FALSE;
1188  return ERROR_INVALID_PARAMETER;
1189  }
1190 
1191  /* FIXME: check we're comparing a string to a column */
1192 
1193  cond->type = EXPR_STRCMP;
1194  }
1195 
1196  break;
1197  case EXPR_UNARY:
1198  if ( cond->u.expr.left->type != EXPR_COLUMN )
1199  {
1200  *valid = FALSE;
1201  return ERROR_INVALID_PARAMETER;
1202  }
1203  r = WHERE_VerifyCondition( wv, cond->u.expr.left, valid );
1204  if( r != ERROR_SUCCESS )
1205  return r;
1206  break;
1207  case EXPR_IVAL:
1208  *valid = 1;
1209  cond->type = EXPR_UVAL;
1210  cond->u.uval = cond->u.ival;
1211  break;
1212  case EXPR_WILDCARD:
1213  *valid = 1;
1214  break;
1215  case EXPR_SVAL:
1216  *valid = 1;
1217  break;
1218  default:
1219  ERR("Invalid expression type\n");
1220  *valid = 0;
1221  break;
1222  }
1223 
1224  return ERROR_SUCCESS;
1225 }
1226 
1228  struct expr *cond )
1229 {
1230  MSIWHEREVIEW *wv = NULL;
1231  UINT r, valid = 0;
1232  WCHAR *ptr;
1233 
1234  TRACE("(%s)\n", debugstr_w(tables) );
1235 
1236  wv = msi_alloc_zero( sizeof *wv );
1237  if( !wv )
1238  return ERROR_FUNCTION_FAILED;
1239 
1240  /* fill the structure */
1241  wv->view.ops = &where_ops;
1242  msiobj_addref( &db->hdr );
1243  wv->db = db;
1244  wv->cond = cond;
1245 
1246  while (*tables)
1247  {
1248  JOINTABLE *table;
1249 
1250  if ((ptr = wcschr(tables, ' ')))
1251  *ptr = '\0';
1252 
1253  table = msi_alloc(sizeof(JOINTABLE));
1254  if (!table)
1255  {
1256  r = ERROR_OUTOFMEMORY;
1257  goto end;
1258  }
1259 
1260  r = TABLE_CreateView(db, tables, &table->view);
1261  if (r != ERROR_SUCCESS)
1262  {
1263  WARN("can't create table: %s\n", debugstr_w(tables));
1264  msi_free(table);
1266  goto end;
1267  }
1268 
1269  r = table->view->ops->get_dimensions(table->view, NULL,
1270  &table->col_count);
1271  if (r != ERROR_SUCCESS)
1272  {
1273  ERR("can't get table dimensions\n");
1274  table->view->ops->delete(table->view);
1275  msi_free(table);
1276  goto end;
1277  }
1278 
1279  wv->col_count += table->col_count;
1280  table->table_index = wv->table_count++;
1281 
1282  table->next = wv->tables;
1283  wv->tables = table;
1284 
1285  if (!ptr)
1286  break;
1287 
1288  tables = ptr + 1;
1289  }
1290 
1291  if( cond )
1292  {
1293  r = WHERE_VerifyCondition( wv, cond, &valid );
1294  if( r != ERROR_SUCCESS )
1295  goto end;
1296  if( !valid ) {
1298  goto end;
1299  }
1300  }
1301 
1302  *view = (MSIVIEW*) wv;
1303 
1304  return ERROR_SUCCESS;
1305 end:
1306  WHERE_delete(&wv->view);
1307 
1308  return r;
1309 }
#define CONST_EXPR
Definition: where.c:747
void msiobj_addref(MSIOBJECTHDR *info)
Definition: handle.c:217
UINT(* delete_row)(struct tagMSIVIEW *view, UINT row)
Definition: msipriv.h:288
const WCHAR * msi_string_lookup(const string_table *st, UINT id, int *len) DECLSPEC_HIDDEN
Definition: string.c:343
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static INT INT_evaluate_binary(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, MSIRECORD *record)
Definition: where.c:418
#define EXPR_COLUMN
Definition: query.h:48
#define JOIN_TO_CONST_EXPR
Definition: where.c:748
static UINT WHERE_set_string(struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
Definition: where.c:282
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
static void add_to_array(JOINTABLE **array, JOINTABLE *elem)
Definition: where.c:732
static UINT WHERE_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: where.c:239
static int __cdecl compare_entry(const void *left, const void *right)
Definition: where.c:685
UINT row_count
Definition: where.c:68
struct complex_expr expr
Definition: query.h:91
static UINT add_row(MSIWHEREVIEW *wv, UINT vals[])
Definition: where.c:125
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:166
static const MSIVIEWOPS where_ops
Definition: where.c:1115
#define ERROR_SUCCESS
Definition: deptool.c:10
struct ext_column::@490 unparsed
#define error(str)
Definition: mkdosfs.c:1605
#define new(TYPE, numElems)
Definition: treelist.c:54
#define __cdecl
Definition: accygwin.h:79
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
UINT TABLE_CreateView(MSIDATABASE *db, LPCWSTR name, MSIVIEW **view) DECLSPEC_HIDDEN
Definition: table.c:2189
static UINT parse_column(MSIWHEREVIEW *wv, union ext_column *column, UINT *column_type)
Definition: where.c:174
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
static UINT expr_fetch_value(const union ext_column *expr, const UINT rows[], UINT *val)
Definition: where.c:494
LPCWSTR sval
Definition: query.h:94
static UINT WHERE_close(struct tagMSIVIEW *view)
Definition: where.c:870
#define TRUE
Definition: types.h:120
UINT col_count
Definition: where.c:51
JOINTABLE * tables
Definition: where.c:67
#define INVALID_ROW_INDEX
Definition: where.c:83
MSIOBJECTHDR hdr
Definition: msipriv.h:151
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint GLuint GLsizei count
Definition: gl.h:1545
struct tagMSIORDERINFO MSIORDERINFO
#define WARN(fmt,...)
Definition: debug.h:112
static UINT STRING_evaluate(MSIWHEREVIEW *wv, const UINT rows[], const struct expr *expr, const MSIRECORD *record, const WCHAR **str)
Definition: where.c:533
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLdouble n
Definition: glext.h:7729
static UINT WHERE_evaluate(MSIWHEREVIEW *wv, const UINT rows[], struct expr *cond, INT *val, MSIRECORD *record)
Definition: where.c:598
static UINT WHERE_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: where.c:887
struct nls_table * tables
Definition: nls_base.c:22
static JOINTABLE * find_table(MSIWHEREVIEW *wv, UINT col, UINT *table_col)
Definition: where.c:156
#define assert(x)
Definition: debug.h:53
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:5644
static void msi_free(void *mem)
Definition: msipriv.h:1159
#define EXPR_COL_NUMBER_STRING
Definition: query.h:55
static UINT WHERE_set_stream(MSIVIEW *view, UINT row, UINT col, IStream *stream)
Definition: where.c:302
#define MSITYPE_STRING
Definition: msipriv.h:50
static UINT WHERE_VerifyCondition(MSIWHEREVIEW *wv, struct expr *cond, UINT *valid)
Definition: where.c:1138
int32_t INT
Definition: typedefs.h:58
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1154
Definition: query.h:86
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
static void free_reorder(MSIWHEREVIEW *wv)
Definition: where.c:85
struct expr * cond
Definition: where.c:73
#define ERROR_CONTINUE
Definition: dderror.h:17
BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) DECLSPEC_HIDDEN
Definition: record.c:957
static UINT INT_evaluate_unary(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, MSIRECORD *record)
Definition: where.c:508
static JOINTABLE ** ordertables(MSIWHEREVIEW *wv)
Definition: where.c:790
UINT col_count
Definition: where.c:69
GLenum GLint GLuint mask
Definition: glext.h:6028
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
#define FALSE
Definition: types.h:117
static UINT WHERE_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: where.c:216
unsigned int BOOL
Definition: ntddk_ex.h:94
string_table * strings
Definition: msipriv.h:110
int type
Definition: query.h:88
union ext_column columns[1]
Definition: where.c:60
static UINT find_row(MSIWHEREVIEW *wv, UINT row, UINT *(values[]))
Definition: where.c:115
UINT table_index
Definition: where.c:53
#define debugstr_w
Definition: kernel32.h:32
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 *))
static size_t elem
Definition: string.c:68
#define EXPR_COL_NUMBER32
Definition: query.h:56
static UINT WHERE_delete_row(struct tagMSIVIEW *view, UINT row)
Definition: where.c:397
static PVOID ptr
Definition: dispmode.c:27
UINT table_count
Definition: where.c:70
union ext_column column
Definition: query.h:95
const WCHAR * str
#define EXPR_STRCMP
Definition: query.h:53
#define EXPR_COL_NUMBER
Definition: query.h:49
WINE_DEFAULT_DEBUG_CHANNEL(msidb)
struct tagJOINTABLE * next
Definition: where.c:49
int MSIMODIFY
Definition: winemsi.idl:33
static UINT WHERE_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: where.c:322
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:433
static UINT check_condition(MSIWHEREVIEW *wv, MSIRECORD *record, JOINTABLE **tables, UINT table_rows[])
Definition: where.c:650
UINT values[1]
Definition: where.c:44
UINT uval
Definition: query.h:93
static UINT join_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec)
Definition: where.c:952
GLuint GLfloat * val
Definition: glext.h:7180
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
static UINT WHERE_set_int(struct tagMSIVIEW *view, UINT row, UINT col, int val)
Definition: where.c:262
static UINT WHERE_delete(struct tagMSIVIEW *view)
Definition: where.c:1035
static UINT WHERE_get_column_info(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: where.c:909
#define TRACE(s)
Definition: solgame.cpp:4
MSIDATABASE * db
Definition: where.c:66
UINT row_count
Definition: where.c:52
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
__wchar_t WCHAR
Definition: xmlstorage.h:180
const MSIVIEWOPS * ops
Definition: msipriv.h:355
GLintptr offset
Definition: glext.h:5920
UINT msi_string2id(const string_table *st, const WCHAR *data, int len, UINT *id) DECLSPEC_HIDDEN
Definition: string.c:400
static UINT STRCMP_Evaluate(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, const MSIRECORD *record)
Definition: where.c:567
GLint left
Definition: glext.h:7726
#define MSITYPE_KEY
Definition: msipriv.h:52
GLdouble GLdouble right
Definition: glext.h:10859
struct task_struct * current
Definition: linux.c:32
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
GLuint GLuint end
Definition: gl.h:1545
#define EXPR_WILDCARD
Definition: query.h:54
struct tagMSIROWENTRY MSIROWENTRY
struct tagJOINTABLE JOINTABLE
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
float rval
Definition: cylfrac.c:48
Definition: parse.h:22
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
static UINT WHERE_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
Definition: where.c:979
static UINT WHERE_execute(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: where.c:814
BOOLEAN valid
#define debugstr_wn
Definition: kernel32.h:33
MSIORDERINFO * order_info
Definition: where.c:75
#define INITIAL_REORDER_SIZE
Definition: where.c:81
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
#define ERR(fmt,...)
Definition: debug.h:110
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
static unsigned __int64 next
Definition: rand_nt.c:6
static UINT join_find_row(MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row)
Definition: where.c:928
static UINT init_reorder(MSIWHEREVIEW *wv)
Definition: where.c:101
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
UINT WHERE_CreateView(MSIDATABASE *db, MSIVIEW **view, LPWSTR tables, struct expr *cond)
Definition: where.c:1227
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
struct tagMSIWHEREVIEW MSIWHEREVIEW
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
INT ival
Definition: query.h:92
UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:353
static UINT reorder_check(const struct expr *expr, JOINTABLE **ordered_tables, BOOL process_joins, JOINTABLE **lastused)
Definition: where.c:751
UINT col_count
Definition: where.c:58
Definition: name.c:38
GLuint res
Definition: glext.h:9613
UINT reorder_size
Definition: where.c:72
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
GLenum GLuint id
Definition: glext.h:5579
#define EXPR_UVAL
Definition: query.h:52
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
union expr::@492 u
UINT rec_index
Definition: where.c:74
WCHAR * LPWSTR
Definition: xmlstorage.h:184
struct tagMSIWHEREVIEW * wv
Definition: where.c:43
MSIVIEW view
Definition: where.c:65
#define memset(x, y, z)
Definition: compat.h:39
static BOOL in_array(JOINTABLE **array, JOINTABLE *elem)
Definition: where.c:740
UINT error
Definition: where.c:59
MSIOBJECTHDR hdr
Definition: msipriv.h:108
#define ERROR_BAD_QUERY_SYNTAX
Definition: winerror.h:973
static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns)
Definition: where.c:1066
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec) DECLSPEC_HIDDEN
Definition: record.c:108
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
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
MSIROWENTRY ** reorder
Definition: where.c:71
MSIVIEW * view
Definition: where.c:50
struct ext_column::@491 parsed