ReactOS  0.4.14-dev-593-g1793dcc
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 "wine/unicode.h"
30 #include "msi.h"
31 #include "msiquery.h"
32 #include "objbase.h"
33 #include "objidl.h"
34 #include "msipriv.h"
35 #include "winnls.h"
36 
37 #include "query.h"
38 
40 
41 /* below is the query interface to a table */
42 typedef struct tagMSIROWENTRY
43 {
44  struct tagMSIWHEREVIEW *wv; /* used during sorting */
46 } MSIROWENTRY;
47 
48 typedef struct tagJOINTABLE
49 {
50  struct tagJOINTABLE *next;
55 } JOINTABLE;
56 
57 typedef struct tagMSIORDERINFO
58 {
61  union ext_column columns[1];
62 } MSIORDERINFO;
63 
64 typedef struct tagMSIWHEREVIEW
65 {
73  UINT reorder_size; /* number of entries available in reorder */
74  struct expr *cond;
77 } MSIWHEREVIEW;
78 
79 static UINT WHERE_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
80  struct expr *cond, INT *val, MSIRECORD *record );
81 
82 #define INITIAL_REORDER_SIZE 16
83 
84 #define INVALID_ROW_INDEX (-1)
85 
86 static void free_reorder(MSIWHEREVIEW *wv)
87 {
88  UINT i;
89 
90  if (!wv->reorder)
91  return;
92 
93  for (i = 0; i < wv->row_count; i++)
94  msi_free(wv->reorder[i]);
95 
96  msi_free( wv->reorder );
97  wv->reorder = NULL;
98  wv->reorder_size = 0;
99  wv->row_count = 0;
100 }
101 
103 {
105  if (!new)
106  return ERROR_OUTOFMEMORY;
107 
108  free_reorder(wv);
109 
110  wv->reorder = new;
112 
113  return ERROR_SUCCESS;
114 }
115 
116 static inline UINT find_row(MSIWHEREVIEW *wv, UINT row, UINT *(values[]))
117 {
118  if (row >= wv->row_count)
119  return ERROR_NO_MORE_ITEMS;
120 
121  *values = wv->reorder[row]->values;
122 
123  return ERROR_SUCCESS;
124 }
125 
126 static UINT add_row(MSIWHEREVIEW *wv, UINT vals[])
127 {
128  MSIROWENTRY *new;
129 
130  if (wv->reorder_size <= wv->row_count)
131  {
132  MSIROWENTRY **new_reorder;
133  UINT newsize = wv->reorder_size * 2;
134 
135  new_reorder = msi_realloc_zero(wv->reorder, sizeof(MSIROWENTRY *) * newsize);
136  if (!new_reorder)
137  return ERROR_OUTOFMEMORY;
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 (strcmpW(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(strcmpW(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_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
263 {
264  MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
265 
266  TRACE("%p %d %p\n", wv, row, rec );
267 
268  if (!wv->tables)
269  return ERROR_FUNCTION_FAILED;
270 
271  return msi_view_get_row( wv->db, view, row, rec );
272 }
273 
275 {
277  UINT i, r, offset = 0;
278  JOINTABLE *table = wv->tables;
279  UINT *rows;
280  UINT mask_copy = mask;
281 
282  TRACE("%p %d %p %08x\n", wv, row, rec, mask );
283 
284  if( !wv->tables )
285  return ERROR_FUNCTION_FAILED;
286 
287  r = find_row(wv, row, &rows);
288  if (r != ERROR_SUCCESS)
289  return r;
290 
291  if (mask >= 1 << wv->col_count)
293 
294  do
295  {
296  for (i = 0; i < table->col_count; i++) {
297  UINT type;
298 
299  if (!(mask_copy & (1 << i)))
300  continue;
301  r = table->view->ops->get_column_info(table->view, i + 1, NULL,
302  &type, NULL, NULL );
303  if (r != ERROR_SUCCESS)
304  return r;
305  if (type & MSITYPE_KEY)
306  return ERROR_FUNCTION_FAILED;
307  }
308  mask_copy >>= table->col_count;
309  }
310  while (mask_copy && (table = table->next));
311 
312  table = wv->tables;
313 
314  do
315  {
316  const UINT col_count = table->col_count;
317  UINT i;
318  MSIRECORD *reduced;
319  UINT reduced_mask = (mask >> offset) & ((1 << col_count) - 1);
320 
321  if (!reduced_mask)
322  {
323  offset += col_count;
324  continue;
325  }
326 
327  reduced = MSI_CreateRecord(col_count);
328  if (!reduced)
329  return ERROR_FUNCTION_FAILED;
330 
331  for (i = 1; i <= col_count; i++)
332  {
333  r = MSI_RecordCopyField(rec, i + offset, reduced, i);
334  if (r != ERROR_SUCCESS)
335  break;
336  }
337 
338  offset += col_count;
339 
340  if (r == ERROR_SUCCESS)
341  r = table->view->ops->set_row(table->view, rows[table->table_index], reduced, reduced_mask);
342 
343  msiobj_release(&reduced->hdr);
344  }
345  while ((table = table->next));
346  return r;
347 }
348 
350 {
351  MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
352  UINT r;
353  UINT *rows;
354 
355  TRACE("(%p %d)\n", view, row);
356 
357  if (!wv->tables)
358  return ERROR_FUNCTION_FAILED;
359 
360  r = find_row(wv, row, &rows);
361  if ( r != ERROR_SUCCESS )
362  return r;
363 
364  if (wv->table_count > 1)
366 
367  return wv->tables->view->ops->delete_row(wv->tables->view, rows[0]);
368 }
369 
370 static INT INT_evaluate_binary( MSIWHEREVIEW *wv, const UINT rows[],
371  const struct complex_expr *expr, INT *val, MSIRECORD *record )
372 {
373  UINT rl, rr;
374  INT lval, rval;
375 
376  rl = WHERE_evaluate(wv, rows, expr->left, &lval, record);
377  if (rl != ERROR_SUCCESS && rl != ERROR_CONTINUE)
378  return rl;
379  rr = WHERE_evaluate(wv, rows, expr->right, &rval, record);
380  if (rr != ERROR_SUCCESS && rr != ERROR_CONTINUE)
381  return rr;
382 
383  if (rl == ERROR_CONTINUE || rr == ERROR_CONTINUE)
384  {
385  if (rl == rr)
386  {
387  *val = TRUE;
388  return ERROR_CONTINUE;
389  }
390 
391  if (expr->op == OP_AND)
392  {
393  if ((rl == ERROR_CONTINUE && !rval) || (rr == ERROR_CONTINUE && !lval))
394  {
395  *val = FALSE;
396  return ERROR_SUCCESS;
397  }
398  }
399  else if (expr->op == OP_OR)
400  {
401  if ((rl == ERROR_CONTINUE && rval) || (rr == ERROR_CONTINUE && lval))
402  {
403  *val = TRUE;
404  return ERROR_SUCCESS;
405  }
406  }
407 
408  *val = TRUE;
409  return ERROR_CONTINUE;
410  }
411 
412  switch( expr->op )
413  {
414  case OP_EQ:
415  *val = ( lval == rval );
416  break;
417  case OP_AND:
418  *val = ( lval && rval );
419  break;
420  case OP_OR:
421  *val = ( lval || rval );
422  break;
423  case OP_GT:
424  *val = ( lval > rval );
425  break;
426  case OP_LT:
427  *val = ( lval < rval );
428  break;
429  case OP_LE:
430  *val = ( lval <= rval );
431  break;
432  case OP_GE:
433  *val = ( lval >= rval );
434  break;
435  case OP_NE:
436  *val = ( lval != rval );
437  break;
438  default:
439  ERR("Unknown operator %d\n", expr->op );
440  return ERROR_FUNCTION_FAILED;
441  }
442 
443  return ERROR_SUCCESS;
444 }
445 
446 static inline UINT expr_fetch_value(const union ext_column *expr, const UINT rows[], UINT *val)
447 {
448  JOINTABLE *table = expr->parsed.table;
449 
450  if( rows[table->table_index] == INVALID_ROW_INDEX )
451  {
452  *val = 1;
453  return ERROR_CONTINUE;
454  }
455  return table->view->ops->fetch_int(table->view, rows[table->table_index],
456  expr->parsed.column, val);
457 }
458 
459 
460 static UINT INT_evaluate_unary( MSIWHEREVIEW *wv, const UINT rows[],
461  const struct complex_expr *expr, INT *val, MSIRECORD *record )
462 {
463  UINT r;
464  UINT lval;
465 
466  r = expr_fetch_value(&expr->left->u.column, rows, &lval);
467  if(r != ERROR_SUCCESS)
468  return r;
469 
470  switch( expr->op )
471  {
472  case OP_ISNULL:
473  *val = !lval;
474  break;
475  case OP_NOTNULL:
476  *val = lval;
477  break;
478  default:
479  ERR("Unknown operator %d\n", expr->op );
480  return ERROR_FUNCTION_FAILED;
481  }
482  return ERROR_SUCCESS;
483 }
484 
485 static UINT STRING_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
486  const struct expr *expr,
487  const MSIRECORD *record,
488  const WCHAR **str )
489 {
490  UINT val = 0, r = ERROR_SUCCESS;
491 
492  switch( expr->type )
493  {
495  r = expr_fetch_value(&expr->u.column, rows, &val);
496  if (r == ERROR_SUCCESS)
497  *str = msi_string_lookup(wv->db->strings, val, NULL);
498  else
499  *str = NULL;
500  break;
501 
502  case EXPR_SVAL:
503  *str = expr->u.sval;
504  break;
505 
506  case EXPR_WILDCARD:
508  break;
509 
510  default:
511  ERR("Invalid expression type\n");
513  *str = NULL;
514  break;
515  }
516  return r;
517 }
518 
519 static UINT STRCMP_Evaluate( MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr,
520  INT *val, const MSIRECORD *record )
521 {
522  int sr;
523  const WCHAR *l_str, *r_str;
524  UINT r;
525 
526  *val = TRUE;
527  r = STRING_evaluate(wv, rows, expr->left, record, &l_str);
528  if (r == ERROR_CONTINUE)
529  return r;
530  r = STRING_evaluate(wv, rows, expr->right, record, &r_str);
531  if (r == ERROR_CONTINUE)
532  return r;
533 
534  if( l_str == r_str ||
535  ((!l_str || !*l_str) && (!r_str || !*r_str)) )
536  sr = 0;
537  else if( l_str && ! r_str )
538  sr = 1;
539  else if( r_str && ! l_str )
540  sr = -1;
541  else
542  sr = strcmpW( l_str, r_str );
543 
544  *val = ( expr->op == OP_EQ && ( sr == 0 ) ) ||
545  ( expr->op == OP_NE && ( sr != 0 ) );
546 
547  return ERROR_SUCCESS;
548 }
549 
550 static UINT WHERE_evaluate( MSIWHEREVIEW *wv, const UINT rows[],
551  struct expr *cond, INT *val, MSIRECORD *record )
552 {
553  UINT r, tval;
554 
555  if( !cond )
556  {
557  *val = TRUE;
558  return ERROR_SUCCESS;
559  }
560 
561  switch( cond->type )
562  {
563  case EXPR_COL_NUMBER:
564  r = expr_fetch_value(&cond->u.column, rows, &tval);
565  if( r != ERROR_SUCCESS )
566  return r;
567  *val = tval - 0x8000;
568  return ERROR_SUCCESS;
569 
570  case EXPR_COL_NUMBER32:
571  r = expr_fetch_value(&cond->u.column, rows, &tval);
572  if( r != ERROR_SUCCESS )
573  return r;
574  *val = tval - 0x80000000;
575  return r;
576 
577  case EXPR_UVAL:
578  *val = cond->u.uval;
579  return ERROR_SUCCESS;
580 
581  case EXPR_COMPLEX:
582  return INT_evaluate_binary(wv, rows, &cond->u.expr, val, record);
583 
584  case EXPR_UNARY:
585  return INT_evaluate_unary( wv, rows, &cond->u.expr, val, record );
586 
587  case EXPR_STRCMP:
588  return STRCMP_Evaluate( wv, rows, &cond->u.expr, val, record );
589 
590  case EXPR_WILDCARD:
592  return ERROR_SUCCESS;
593 
594  default:
595  ERR("Invalid expression type\n");
596  return ERROR_FUNCTION_FAILED;
597  }
598 
599  return ERROR_SUCCESS;
600 }
601 
603  UINT table_rows[] )
604 {
606  INT val;
607 
608  for (table_rows[(*tables)->table_index] = 0;
609  table_rows[(*tables)->table_index] < (*tables)->row_count;
610  table_rows[(*tables)->table_index]++)
611  {
612  val = 0;
613  wv->rec_index = 0;
614  r = WHERE_evaluate( wv, table_rows, wv->cond, &val, record );
615  if (r != ERROR_SUCCESS && r != ERROR_CONTINUE)
616  break;
617  if (val)
618  {
619  if (*(tables + 1))
620  {
621  r = check_condition(wv, record, tables + 1, table_rows);
622  if (r != ERROR_SUCCESS)
623  break;
624  }
625  else
626  {
627  if (r != ERROR_SUCCESS)
628  break;
629  add_row (wv, table_rows);
630  }
631  }
632  }
633  table_rows[(*tables)->table_index] = INVALID_ROW_INDEX;
634  return r;
635 }
636 
637 static int compare_entry( const void *left, const void *right )
638 {
639  const MSIROWENTRY *le = *(const MSIROWENTRY**)left;
640  const MSIROWENTRY *re = *(const MSIROWENTRY**)right;
641  const MSIWHEREVIEW *wv = le->wv;
643  UINT i, j, r, l_val, r_val;
644 
645  assert(le->wv == re->wv);
646 
647  if (order)
648  {
649  for (i = 0; i < order->col_count; i++)
650  {
651  const union ext_column *column = &order->columns[i];
652 
653  r = column->parsed.table->view->ops->fetch_int(column->parsed.table->view,
654  le->values[column->parsed.table->table_index],
655  column->parsed.column, &l_val);
656  if (r != ERROR_SUCCESS)
657  {
658  order->error = r;
659  return 0;
660  }
661 
662  r = column->parsed.table->view->ops->fetch_int(column->parsed.table->view,
663  re->values[column->parsed.table->table_index],
664  column->parsed.column, &r_val);
665  if (r != ERROR_SUCCESS)
666  {
667  order->error = r;
668  return 0;
669  }
670 
671  if (l_val != r_val)
672  return l_val < r_val ? -1 : 1;
673  }
674  }
675 
676  for (j = 0; j < wv->table_count; j++)
677  {
678  if (le->values[j] != re->values[j])
679  return le->values[j] < re->values[j] ? -1 : 1;
680  }
681  return 0;
682 }
683 
685 {
686  while (*array && *array != elem)
687  array++;
688  if (!*array)
689  *array = elem;
690 }
691 
693 {
694  while (*array && *array != elem)
695  array++;
696  return *array != NULL;
697 }
698 
699 #define CONST_EXPR 1 /* comparison to a constant value */
700 #define JOIN_TO_CONST_EXPR 0x10000 /* comparison to a table involved with
701  a CONST_EXPR comaprison */
702 
703 static UINT reorder_check( const struct expr *expr, JOINTABLE **ordered_tables,
704  BOOL process_joins, JOINTABLE **lastused )
705 {
706  UINT res = 0;
707 
708  switch (expr->type)
709  {
710  case EXPR_WILDCARD:
711  case EXPR_SVAL:
712  case EXPR_UVAL:
713  return 0;
714  case EXPR_COL_NUMBER:
715  case EXPR_COL_NUMBER32:
717  if (in_array(ordered_tables, expr->u.column.parsed.table))
718  return JOIN_TO_CONST_EXPR;
719  *lastused = expr->u.column.parsed.table;
720  return CONST_EXPR;
721  case EXPR_STRCMP:
722  case EXPR_COMPLEX:
723  res = reorder_check(expr->u.expr.right, ordered_tables, process_joins, lastused);
724  /* fall through */
725  case EXPR_UNARY:
726  res += reorder_check(expr->u.expr.left, ordered_tables, process_joins, lastused);
727  if (res == 0)
728  return 0;
729  if (res == CONST_EXPR)
730  add_to_array(ordered_tables, *lastused);
731  if (process_joins && res == JOIN_TO_CONST_EXPR + CONST_EXPR)
732  add_to_array(ordered_tables, *lastused);
733  return res;
734  default:
735  ERR("Unknown expr type: %i\n", expr->type);
736  assert(0);
737  return 0x1000000;
738  }
739 }
740 
741 /* reorders the tablelist in a way to evaluate the condition as fast as possible */
743 {
744  JOINTABLE *table;
745  JOINTABLE **tables;
746 
747  tables = msi_alloc_zero( (wv->table_count + 1) * sizeof(*tables) );
748 
749  if (wv->cond)
750  {
751  table = NULL;
753  table = NULL;
755  }
756 
757  table = wv->tables;
758  while (table)
759  {
761  table = table->next;
762  }
763  return tables;
764 }
765 
767 {
769  UINT r;
770  JOINTABLE *table = wv->tables;
771  UINT *rows;
772  JOINTABLE **ordered_tables;
773  UINT i = 0;
774 
775  TRACE("%p %p\n", wv, record);
776 
777  if( !table )
778  return ERROR_FUNCTION_FAILED;
779 
780  r = init_reorder(wv);
781  if (r != ERROR_SUCCESS)
782  return r;
783 
784  do
785  {
786  table->view->ops->execute(table->view, NULL);
787 
788  r = table->view->ops->get_dimensions(table->view, &table->row_count, NULL);
789  if (r != ERROR_SUCCESS)
790  {
791  ERR("failed to get table dimensions\n");
792  return r;
793  }
794 
795  /* each table must have at least one row */
796  if (table->row_count == 0)
797  return ERROR_SUCCESS;
798  }
799  while ((table = table->next));
800 
801  ordered_tables = ordertables( wv );
802 
803  rows = msi_alloc( wv->table_count * sizeof(*rows) );
804  for (i = 0; i < wv->table_count; i++)
805  rows[i] = INVALID_ROW_INDEX;
806 
807  r = check_condition(wv, record, ordered_tables, rows);
808 
809  if (wv->order_info)
811 
812  qsort(wv->reorder, wv->row_count, sizeof(MSIROWENTRY *), compare_entry);
813 
814  if (wv->order_info)
815  r = wv->order_info->error;
816 
817  msi_free( rows );
818  msi_free( ordered_tables );
819  return r;
820 }
821 
822 static UINT WHERE_close( struct tagMSIVIEW *view )
823 {
825  JOINTABLE *table = wv->tables;
826 
827  TRACE("%p\n", wv );
828 
829  if (!table)
830  return ERROR_FUNCTION_FAILED;
831 
832  do
833  table->view->ops->close(table->view);
834  while ((table = table->next));
835 
836  return ERROR_SUCCESS;
837 }
838 
839 static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
840 {
842 
843  TRACE("%p %p %p\n", wv, rows, cols );
844 
845  if(!wv->tables)
846  return ERROR_FUNCTION_FAILED;
847 
848  if (rows)
849  {
850  if (!wv->reorder)
851  return ERROR_FUNCTION_FAILED;
852  *rows = wv->row_count;
853  }
854 
855  if (cols)
856  *cols = wv->col_count;
857 
858  return ERROR_SUCCESS;
859 }
860 
862  UINT *type, BOOL *temporary, LPCWSTR *table_name )
863 {
865  JOINTABLE *table;
866 
867  TRACE("%p %d %p %p %p %p\n", wv, n, name, type, temporary, table_name );
868 
869  if(!wv->tables)
870  return ERROR_FUNCTION_FAILED;
871 
872  table = find_table(wv, n, &n);
873  if (!table)
874  return ERROR_FUNCTION_FAILED;
875 
876  return table->view->ops->get_column_info(table->view, n, name,
877  type, temporary, table_name);
878 }
879 
881 {
882  LPCWSTR str;
883  UINT r, i, id, data;
884 
885  str = MSI_RecordGetString( rec, 1 );
886  r = msi_string2id( wv->db->strings, str, -1, &id );
887  if (r != ERROR_SUCCESS)
888  return r;
889 
890  for (i = 0; i < wv->row_count; i++)
891  {
892  WHERE_fetch_int( &wv->view, i, 1, &data );
893 
894  if (data == id)
895  {
896  *row = i;
897  return ERROR_SUCCESS;
898  }
899  }
900 
901  return ERROR_FUNCTION_FAILED;
902 }
903 
905 {
906  MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
907  UINT r, row, i, mask = 0;
909 
910 
911  r = join_find_row( wv, rec, &row );
912  if (r != ERROR_SUCCESS)
913  return r;
914 
915  r = msi_view_get_row( wv->db, view, row, &current );
916  if (r != ERROR_SUCCESS)
917  return r;
918 
920 
921  for (i = MSI_RecordGetFieldCount(rec); i > 0; i--)
922  {
923  if (!MSI_RecordsAreFieldsEqual(rec, current, i))
924  mask |= 1 << (i - 1);
925  }
926  msiobj_release(&current->hdr);
927 
928  return WHERE_set_row( view, row, rec, mask );
929 }
930 
931 static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
932  MSIRECORD *rec, UINT row )
933 {
935  JOINTABLE *table = wv->tables;
936  UINT r;
937 
938  TRACE("%p %d %p\n", wv, eModifyMode, rec);
939 
940  if (!table)
941  return ERROR_FUNCTION_FAILED;
942 
943  if (!table->next)
944  {
945  UINT *rows;
946 
947  if (find_row(wv, row - 1, &rows) == ERROR_SUCCESS)
948  row = rows[0] + 1;
949  else
950  row = -1;
951 
952  return table->view->ops->modify(table->view, eModifyMode, rec, row);
953  }
954 
955  switch (eModifyMode)
956  {
957  case MSIMODIFY_UPDATE:
958  return join_modify_update( view, rec );
959 
960  case MSIMODIFY_ASSIGN:
961  case MSIMODIFY_DELETE:
962  case MSIMODIFY_INSERT:
964  case MSIMODIFY_MERGE:
965  case MSIMODIFY_REPLACE:
966  case MSIMODIFY_SEEK:
967  case MSIMODIFY_VALIDATE:
972  break;
973 
974  case MSIMODIFY_REFRESH:
976  break;
977 
978  default:
979  WARN("%p %d %p %u - unknown mode\n", view, eModifyMode, rec, row );
981  break;
982  }
983 
984  return r;
985 }
986 
987 static UINT WHERE_delete( struct tagMSIVIEW *view )
988 {
990  JOINTABLE *table = wv->tables;
991 
992  TRACE("%p\n", wv );
993 
994  while(table)
995  {
996  JOINTABLE *next;
997 
998  table->view->ops->delete(table->view);
999  table->view = NULL;
1000  next = table->next;
1001  msi_free(table);
1002  table = next;
1003  }
1004  wv->tables = NULL;
1005  wv->table_count = 0;
1006 
1007  free_reorder(wv);
1008 
1009  msi_free(wv->order_info);
1010  wv->order_info = NULL;
1011 
1012  msiobj_release( &wv->db->hdr );
1013  msi_free( wv );
1014 
1015  return ERROR_SUCCESS;
1016 }
1017 
1020 {
1021  MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
1022  UINT i, row_value;
1023 
1024  TRACE("%p, %d, %u, %p\n", view, col, val, *handle);
1025 
1026  if (!wv->tables)
1027  return ERROR_FUNCTION_FAILED;
1028 
1029  if (col == 0 || col > wv->col_count)
1030  return ERROR_INVALID_PARAMETER;
1031 
1032  for (i = PtrToUlong(*handle); i < wv->row_count; i++)
1033  {
1034  if (view->ops->fetch_int( view, i, col, &row_value ) != ERROR_SUCCESS)
1035  continue;
1036 
1037  if (row_value == val)
1038  {
1039  *row = i;
1040  *handle = UlongToPtr(i + 1);
1041  return ERROR_SUCCESS;
1042  }
1043  }
1044 
1045  return ERROR_NO_MORE_ITEMS;
1046 }
1047 
1048 static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns)
1049 {
1050  MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
1051  JOINTABLE *table = wv->tables;
1052  column_info *column = columns;
1053  MSIORDERINFO *orderinfo;
1054  UINT r, count = 0;
1055  UINT i;
1056 
1057  TRACE("%p %p\n", view, columns);
1058 
1059  if (!table)
1060  return ERROR_FUNCTION_FAILED;
1061 
1062  while (column)
1063  {
1064  count++;
1065  column = column->next;
1066  }
1067 
1068  if (count == 0)
1069  return ERROR_SUCCESS;
1070 
1071  orderinfo = msi_alloc(FIELD_OFFSET(MSIORDERINFO, columns[count]));
1072  if (!orderinfo)
1073  return ERROR_OUTOFMEMORY;
1074 
1075  orderinfo->col_count = count;
1076 
1077  column = columns;
1078 
1079  for (i = 0; i < count; i++)
1080  {
1081  orderinfo->columns[i].unparsed.column = column->column;
1082  orderinfo->columns[i].unparsed.table = column->table;
1083 
1084  r = parse_column(wv, &orderinfo->columns[i], NULL);
1085  if (r != ERROR_SUCCESS)
1086  goto error;
1087  }
1088 
1089  wv->order_info = orderinfo;
1090 
1091  return ERROR_SUCCESS;
1092 error:
1093  msi_free(orderinfo);
1094  return r;
1095 }
1096 
1097 static const MSIVIEWOPS where_ops =
1098 {
1101  WHERE_get_row,
1102  WHERE_set_row,
1103  NULL,
1105  WHERE_execute,
1106  WHERE_close,
1109  WHERE_modify,
1110  WHERE_delete,
1112  NULL,
1113  NULL,
1114  NULL,
1115  NULL,
1116  WHERE_sort,
1117  NULL,
1118 };
1119 
1120 static UINT WHERE_VerifyCondition( MSIWHEREVIEW *wv, struct expr *cond,
1121  UINT *valid )
1122 {
1123  UINT r;
1124 
1125  switch( cond->type )
1126  {
1127  case EXPR_COLUMN:
1128  {
1129  UINT type;
1130 
1131  *valid = FALSE;
1132 
1133  r = parse_column(wv, &cond->u.column, &type);
1134  if (r != ERROR_SUCCESS)
1135  break;
1136 
1137  if (type&MSITYPE_STRING)
1138  cond->type = EXPR_COL_NUMBER_STRING;
1139  else if ((type&0xff) == 4)
1140  cond->type = EXPR_COL_NUMBER32;
1141  else
1142  cond->type = EXPR_COL_NUMBER;
1143 
1144  *valid = TRUE;
1145  break;
1146  }
1147  case EXPR_COMPLEX:
1148  r = WHERE_VerifyCondition( wv, cond->u.expr.left, valid );
1149  if( r != ERROR_SUCCESS )
1150  return r;
1151  if( !*valid )
1152  return ERROR_SUCCESS;
1153  r = WHERE_VerifyCondition( wv, cond->u.expr.right, valid );
1154  if( r != ERROR_SUCCESS )
1155  return r;
1156 
1157  /* check the type of the comparison */
1158  if( ( cond->u.expr.left->type == EXPR_SVAL ) ||
1159  ( cond->u.expr.left->type == EXPR_COL_NUMBER_STRING ) ||
1160  ( cond->u.expr.right->type == EXPR_SVAL ) ||
1161  ( cond->u.expr.right->type == EXPR_COL_NUMBER_STRING ) )
1162  {
1163  switch( cond->u.expr.op )
1164  {
1165  case OP_EQ:
1166  case OP_NE:
1167  break;
1168  default:
1169  *valid = FALSE;
1170  return ERROR_INVALID_PARAMETER;
1171  }
1172 
1173  /* FIXME: check we're comparing a string to a column */
1174 
1175  cond->type = EXPR_STRCMP;
1176  }
1177 
1178  break;
1179  case EXPR_UNARY:
1180  if ( cond->u.expr.left->type != EXPR_COLUMN )
1181  {
1182  *valid = FALSE;
1183  return ERROR_INVALID_PARAMETER;
1184  }
1185  r = WHERE_VerifyCondition( wv, cond->u.expr.left, valid );
1186  if( r != ERROR_SUCCESS )
1187  return r;
1188  break;
1189  case EXPR_IVAL:
1190  *valid = 1;
1191  cond->type = EXPR_UVAL;
1192  cond->u.uval = cond->u.ival;
1193  break;
1194  case EXPR_WILDCARD:
1195  *valid = 1;
1196  break;
1197  case EXPR_SVAL:
1198  *valid = 1;
1199  break;
1200  default:
1201  ERR("Invalid expression type\n");
1202  *valid = 0;
1203  break;
1204  }
1205 
1206  return ERROR_SUCCESS;
1207 }
1208 
1210  struct expr *cond )
1211 {
1212  MSIWHEREVIEW *wv = NULL;
1213  UINT r, valid = 0;
1214  WCHAR *ptr;
1215 
1216  TRACE("(%s)\n", debugstr_w(tables) );
1217 
1218  wv = msi_alloc_zero( sizeof *wv );
1219  if( !wv )
1220  return ERROR_FUNCTION_FAILED;
1221 
1222  /* fill the structure */
1223  wv->view.ops = &where_ops;
1224  msiobj_addref( &db->hdr );
1225  wv->db = db;
1226  wv->cond = cond;
1227 
1228  while (*tables)
1229  {
1230  JOINTABLE *table;
1231 
1232  if ((ptr = strchrW(tables, ' ')))
1233  *ptr = '\0';
1234 
1235  table = msi_alloc(sizeof(JOINTABLE));
1236  if (!table)
1237  {
1238  r = ERROR_OUTOFMEMORY;
1239  goto end;
1240  }
1241 
1242  r = TABLE_CreateView(db, tables, &table->view);
1243  if (r != ERROR_SUCCESS)
1244  {
1245  WARN("can't create table: %s\n", debugstr_w(tables));
1246  msi_free(table);
1248  goto end;
1249  }
1250 
1251  r = table->view->ops->get_dimensions(table->view, NULL,
1252  &table->col_count);
1253  if (r != ERROR_SUCCESS)
1254  {
1255  ERR("can't get table dimensions\n");
1256  table->view->ops->delete(table->view);
1257  msi_free(table);
1258  goto end;
1259  }
1260 
1261  wv->col_count += table->col_count;
1262  table->table_index = wv->table_count++;
1263 
1264  table->next = wv->tables;
1265  wv->tables = table;
1266 
1267  if (!ptr)
1268  break;
1269 
1270  tables = ptr + 1;
1271  }
1272 
1273  if( cond )
1274  {
1275  r = WHERE_VerifyCondition( wv, cond, &valid );
1276  if( r != ERROR_SUCCESS )
1277  goto end;
1278  if( !valid ) {
1280  goto end;
1281  }
1282  }
1283 
1284  *view = (MSIVIEW*) wv;
1285 
1286  return ERROR_SUCCESS;
1287 end:
1288  WHERE_delete(&wv->view);
1289 
1290  return r;
1291 }
#define CONST_EXPR
Definition: where.c:699
void msiobj_addref(MSIOBJECTHDR *info)
Definition: handle.c:218
UINT(* delete_row)(struct tagMSIVIEW *view, UINT row)
Definition: msipriv.h:263
const WCHAR * msi_string_lookup(const string_table *st, UINT id, int *len) DECLSPEC_HIDDEN
Definition: string.c:347
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static INT INT_evaluate_binary(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, MSIRECORD *record)
Definition: where.c:370
#define EXPR_COLUMN
Definition: query.h:48
#define JOIN_TO_CONST_EXPR
Definition: where.c:700
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
static void add_to_array(JOINTABLE **array, JOINTABLE *elem)
Definition: where.c:684
static UINT WHERE_find_matching_rows(struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle)
Definition: where.c:1018
static UINT WHERE_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: where.c:239
#define TRUE
Definition: types.h:120
UINT row_count
Definition: where.c:69
struct complex_expr expr
Definition: query.h:91
#define OP_EQ
Definition: query.h:36
static UINT add_row(MSIWHEREVIEW *wv, UINT vals[])
Definition: where.c:126
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:169
#define OP_GE
Definition: query.h:42
static const MSIVIEWOPS where_ops
Definition: where.c:1097
#define ERROR_SUCCESS
Definition: deptool.c:10
#define error(str)
Definition: mkdosfs.c:1605
#define new(TYPE, numElems)
Definition: treelist.c:54
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
UINT TABLE_CreateView(MSIDATABASE *db, LPCWSTR name, MSIVIEW **view) DECLSPEC_HIDDEN
Definition: table.c:2162
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:95
static UINT expr_fetch_value(const union ext_column *expr, const UINT rows[], UINT *val)
Definition: where.c:446
LPCWSTR sval
Definition: query.h:94
static UINT WHERE_close(struct tagMSIVIEW *view)
Definition: where.c:822
struct ext_column::@489 parsed
UINT col_count
Definition: where.c:52
JOINTABLE * tables
Definition: where.c:68
#define INVALID_ROW_INDEX
Definition: where.c:84
MSIOBJECTHDR hdr
Definition: msipriv.h:141
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
GLuint GLuint GLsizei count
Definition: gl.h:1545
struct tagMSIORDERINFO MSIORDERINFO
#define WARN(fmt,...)
Definition: debug.h:111
static UINT STRING_evaluate(MSIWHEREVIEW *wv, const UINT rows[], const struct expr *expr, const MSIRECORD *record, const WCHAR **str)
Definition: where.c:485
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLintptr offset
Definition: glext.h:5920
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:550
static UINT WHERE_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: where.c:839
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static JOINTABLE * find_table(MSIWHEREVIEW *wv, UINT col, UINT *table_col)
Definition: where.c:156
static int compare_entry(const void *left, const void *right)
Definition: where.c:637
#define assert(x)
Definition: debug.h:53
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:5644
#define EXPR_COL_NUMBER_STRING
Definition: query.h:55
GLuint GLuint end
Definition: gl.h:1545
#define MSITYPE_STRING
Definition: msipriv.h:47
static UINT WHERE_VerifyCondition(MSIWHEREVIEW *wv, struct expr *cond, UINT *valid)
Definition: where.c:1120
int32_t INT
Definition: typedefs.h:56
Definition: query.h:86
#define OP_AND
Definition: query.h:37
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1210
static void free_reorder(MSIWHEREVIEW *wv)
Definition: where.c:86
struct expr * cond
Definition: where.c:74
#define ERROR_CONTINUE
Definition: dderror.h:17
BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) DECLSPEC_HIDDEN
Definition: record.c:1010
static UINT INT_evaluate_unary(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, MSIRECORD *record)
Definition: where.c:460
static JOINTABLE ** ordertables(MSIWHEREVIEW *wv)
Definition: where.c:742
UINT col_count
Definition: where.c:70
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
GLenum GLint GLuint mask
Definition: glext.h:6028
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
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:99
int type
Definition: query.h:88
union ext_column columns[1]
Definition: where.c:61
static UINT find_row(MSIWHEREVIEW *wv, UINT row, UINT *(values[]))
Definition: where.c:116
UINT table_index
Definition: where.c:54
#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:349
static PVOID ptr
Definition: dispmode.c:27
UINT table_count
Definition: where.c:71
union ext_column column
Definition: query.h:95
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
#define EXPR_STRCMP
Definition: query.h:53
#define EXPR_COL_NUMBER
Definition: query.h:49
union expr::@490 u
WINE_DEFAULT_DEBUG_CHANNEL(msidb)
struct tagJOINTABLE * next
Definition: where.c:50
#define OP_NE
Definition: query.h:43
static UINT WHERE_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: where.c:274
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:482
static UINT check_condition(MSIWHEREVIEW *wv, MSIRECORD *record, JOINTABLE **tables, UINT table_rows[])
Definition: where.c:602
UINT values[1]
Definition: where.c:45
UINT uval
Definition: query.h:93
static UINT join_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec)
Definition: where.c:904
#define UlongToPtr(u)
Definition: config.h:106
#define PtrToUlong(u)
Definition: config.h:107
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_delete(struct tagMSIVIEW *view)
Definition: where.c:987
static UINT WHERE_get_column_info(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: where.c:861
#define TRACE(s)
Definition: solgame.cpp:4
MSIDATABASE * db
Definition: where.c:67
UINT row_count
Definition: where.c:53
__wchar_t WCHAR
Definition: xmlstorage.h:180
const MSIVIEWOPS * ops
Definition: msipriv.h:348
UINT msi_string2id(const string_table *st, const WCHAR *data, int len, UINT *id) DECLSPEC_HIDDEN
Definition: string.c:404
static UINT WHERE_get_row(struct tagMSIVIEW *view, UINT row, MSIRECORD **rec)
Definition: where.c:262
static UINT STRCMP_Evaluate(MSIWHEREVIEW *wv, const UINT rows[], const struct complex_expr *expr, INT *val, const MSIRECORD *record)
Definition: where.c:519
GLint left
Definition: glext.h:7726
struct ext_column::@488 unparsed
#define MSITYPE_KEY
Definition: msipriv.h:49
GLdouble GLdouble right
Definition: glext.h:10859
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define OP_LE
Definition: query.h:41
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:242
#define EXPR_WILDCARD
Definition: query.h:54
struct tagMSIROWENTRY MSIROWENTRY
struct tagJOINTABLE JOINTABLE
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:79
float rval
Definition: cylfrac.c:48
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static UINT WHERE_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
Definition: where.c:931
static UINT WHERE_execute(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: where.c:766
MSIORDERINFO * order_info
Definition: where.c:76
#define INITIAL_REORDER_SIZE
Definition: where.c:82
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:245
#define ERR(fmt,...)
Definition: debug.h:109
static unsigned __int64 next
Definition: rand_nt.c:6
static UINT join_find_row(MSIWHEREVIEW *wv, MSIRECORD *rec, UINT *row)
Definition: where.c:880
static UINT init_reorder(MSIWHEREVIEW *wv)
Definition: where.c:102
UINT WHERE_CreateView(MSIDATABASE *db, MSIVIEW **view, LPWSTR tables, struct expr *cond)
Definition: where.c:1209
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
struct tagMSIWHEREVIEW MSIWHEREVIEW
enum tagMSIMODIFY MSIMODIFY
unsigned int UINT
Definition: ndis.h:50
INT ival
Definition: query.h:92
UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:287
#define OP_OR
Definition: query.h:38
static UINT reorder_check(const struct expr *expr, JOINTABLE **ordered_tables, BOOL process_joins, JOINTABLE **lastused)
Definition: where.c:703
static BOOL msi_free(void *mem)
Definition: msipriv.h:1227
UINT col_count
Definition: where.c:59
Definition: name.c:38
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
GLuint res
Definition: glext.h:9613
UINT reorder_size
Definition: where.c:73
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1204
GLenum GLuint id
Definition: glext.h:5579
#define EXPR_UVAL
Definition: query.h:52
struct nls_table * tables
Definition: nls_base.c:22
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
static void * msi_realloc_zero(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1222
UINT rec_index
Definition: where.c:75
WCHAR * LPWSTR
Definition: xmlstorage.h:184
struct tagMSIWHEREVIEW * wv
Definition: where.c:44
MSIVIEW view
Definition: where.c:66
static BOOL in_array(JOINTABLE **array, JOINTABLE *elem)
Definition: where.c:692
UINT error
Definition: where.c:60
MSIOBJECTHDR hdr
Definition: msipriv.h:97
#define ERROR_BAD_QUERY_SYNTAX
Definition: winerror.h:973
static UINT WHERE_sort(struct tagMSIVIEW *view, column_info *columns)
Definition: where.c:1048
struct task_struct * current
Definition: linux.c:32
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec) DECLSPEC_HIDDEN
Definition: record.c:111
#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:72
MSIVIEW * view
Definition: where.c:51