Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / msi / where.c
blobd90ddc2f59987723035ee67bbebf6e4490283f4d
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002 Mike McCormack for Codeweavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "wine/debug.h"
27 #include "msi.h"
28 #include "msiquery.h"
29 #include "objbase.h"
30 #include "objidl.h"
31 #include "msipriv.h"
32 #include "winnls.h"
34 #include "query.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msi);
39 /* below is the query interface to a table */
41 typedef struct tagMSIWHEREVIEW
43 MSIVIEW view;
44 MSIDATABASE *db;
45 MSIVIEW *table;
46 UINT row_count;
47 UINT *reorder;
48 struct expr *cond;
49 } MSIWHEREVIEW;
51 static UINT WHERE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
53 MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
55 TRACE("%p %d %d %p\n", wv, row, col, val );
57 if( !wv->table )
58 return ERROR_FUNCTION_FAILED;
60 if( row > wv->row_count )
61 return ERROR_NO_MORE_ITEMS;
63 row = wv->reorder[ row ];
65 return wv->table->ops->fetch_int( wv->table, row, col, val );
68 static UINT INT_evaluate( UINT lval, UINT op, UINT rval )
70 switch( op )
72 case OP_EQ:
73 return ( lval == rval );
74 case OP_AND:
75 return ( lval && rval );
76 case OP_OR:
77 return ( lval || rval );
78 case OP_GT:
79 return ( lval > rval );
80 case OP_LT:
81 return ( lval < rval );
82 case OP_LE:
83 return ( lval <= rval );
84 case OP_GE:
85 return ( lval >= rval );
86 case OP_NE:
87 return ( lval != rval );
88 case OP_ISNULL:
89 return ( !lval );
90 case OP_NOTNULL:
91 return ( lval );
92 default:
93 ERR("Unknown operator %d\n", op );
95 return 0;
98 static UINT WHERE_evaluate( MSIVIEW *table, UINT row,
99 struct expr *cond, UINT *val )
101 UINT r, lval, rval;
103 if( !cond )
104 return ERROR_SUCCESS;
106 switch( cond->type )
108 case EXPR_COL_NUMBER:
109 return table->ops->fetch_int( table, row, cond->u.col_number, val );
111 /* case EXPR_IVAL:
112 *val = cond->u.ival;
113 return ERROR_SUCCESS; */
115 case EXPR_UVAL:
116 *val = cond->u.uval;
117 return ERROR_SUCCESS;
119 case EXPR_COMPLEX:
120 r = WHERE_evaluate( table, row, cond->u.expr.left, &lval );
121 if( r != ERROR_SUCCESS )
122 return r;
123 r = WHERE_evaluate( table, row, cond->u.expr.right, &rval );
124 if( r != ERROR_SUCCESS )
125 return r;
126 *val = INT_evaluate( lval, cond->u.expr.op, rval );
127 return ERROR_SUCCESS;
129 default:
130 ERR("Invalid expression type\n");
131 break;
134 return ERROR_SUCCESS;
138 static UINT WHERE_execute( struct tagMSIVIEW *view, MSIHANDLE record )
140 MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
141 UINT count = 0, r, val, i;
142 MSIVIEW *table = wv->table;
144 TRACE("%p %ld\n", wv, record);
146 if( !table )
147 return ERROR_FUNCTION_FAILED;
149 r = table->ops->execute( table, record );
150 if( r != ERROR_SUCCESS )
151 return r;
153 r = table->ops->get_dimensions( table, &count, NULL );
154 if( r != ERROR_SUCCESS )
155 return r;
157 wv->reorder = HeapAlloc( GetProcessHeap(), 0, count*sizeof(UINT) );
158 if( !wv->reorder )
159 return ERROR_FUNCTION_FAILED;
161 for( i=0; i<count; i++ )
163 val = 0;
164 r = WHERE_evaluate( table, i, wv->cond, &val );
165 if( r != ERROR_SUCCESS )
166 return r;
167 if( val )
168 wv->reorder[ wv->row_count ++ ] = i;
171 return ERROR_SUCCESS;
174 static UINT WHERE_close( struct tagMSIVIEW *view )
176 MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
178 TRACE("%p\n", wv );
180 if( !wv->table )
181 return ERROR_FUNCTION_FAILED;
183 if( wv->reorder )
184 HeapFree( GetProcessHeap(), 0, wv->reorder );
185 wv->reorder = NULL;
187 return wv->table->ops->close( wv->table );
190 static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
192 MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
194 TRACE("%p %p %p\n", wv, rows, cols );
196 if( !wv->table )
197 return ERROR_FUNCTION_FAILED;
199 if( rows )
201 if( !wv->reorder )
202 return ERROR_FUNCTION_FAILED;
203 *rows = wv->row_count;
206 return wv->table->ops->get_dimensions( wv->table, NULL, cols );
209 static UINT WHERE_get_column_info( struct tagMSIVIEW *view,
210 UINT n, LPWSTR *name, UINT *type )
212 MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
214 TRACE("%p %d %p %p\n", wv, n, name, type );
216 if( !wv->table )
217 return ERROR_FUNCTION_FAILED;
219 return wv->table->ops->get_column_info( wv->table, n, name, type );
222 static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIHANDLE hrec)
224 MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
226 TRACE("%p %d %ld\n", wv, eModifyMode, hrec );
228 if( !wv->table )
229 return ERROR_FUNCTION_FAILED;
231 return wv->table->ops->modify( wv->table, eModifyMode, hrec );
234 static void WHERE_delete_expr( struct expr *e )
236 if( !e )
237 return;
238 if( e->type == EXPR_COMPLEX )
240 WHERE_delete_expr( e->u.expr.left );
241 WHERE_delete_expr( e->u.expr.right );
243 HeapFree( GetProcessHeap(), 0, e );
246 static UINT WHERE_delete( struct tagMSIVIEW *view )
248 MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
250 TRACE("%p\n", wv );
252 if( wv->table )
253 wv->table->ops->delete( wv->table );
255 if( wv->reorder )
256 HeapFree( GetProcessHeap(), 0, wv->reorder );
257 wv->reorder = NULL;
258 wv->row_count = 0;
260 WHERE_delete_expr( wv->cond );
262 HeapFree( GetProcessHeap(), 0, wv );
264 return ERROR_SUCCESS;
268 MSIVIEWOPS where_ops =
270 WHERE_fetch_int,
271 WHERE_execute,
272 WHERE_close,
273 WHERE_get_dimensions,
274 WHERE_get_column_info,
275 WHERE_modify,
276 WHERE_delete
279 UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
281 MSIWHEREVIEW *wv = NULL;
282 UINT count = 0, r;
284 TRACE("%p\n", wv );
286 r = table->ops->get_dimensions( table, NULL, &count );
287 if( r != ERROR_SUCCESS )
289 ERR("can't get table dimensions\n");
290 return r;
293 wv = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *wv );
294 if( !wv )
295 return ERROR_FUNCTION_FAILED;
297 /* fill the structure */
298 wv->view.ops = &where_ops;
299 wv->db = db;
300 wv->table = table;
301 wv->row_count = 0;
302 wv->reorder = NULL;
303 *view = (MSIVIEW*) wv;
305 return ERROR_SUCCESS;
308 static UINT WHERE_VerifyCondition( MSIVIEW *table, struct expr *cond,
309 UINT *valid )
311 UINT r, col = 0;
313 switch( cond->type )
315 case EXPR_COLUMN:
316 r = VIEW_find_column( table, cond->u.column, &col );
317 if( r == ERROR_SUCCESS )
319 *valid = 1;
320 cond->type = EXPR_COL_NUMBER;
321 cond->u.col_number = col;
323 else
325 *valid = 0;
326 ERR("Couldn't find column %s\n", debugstr_w( cond->u.column ) );
328 break;
329 case EXPR_COMPLEX:
330 r = WHERE_VerifyCondition( table, cond->u.expr.left, valid );
331 if( r != ERROR_SUCCESS )
332 return r;
333 if( !*valid )
334 return ERROR_SUCCESS;
335 r = WHERE_VerifyCondition( table, cond->u.expr.right, valid );
336 if( r != ERROR_SUCCESS )
337 return r;
338 break;
339 case EXPR_IVAL:
340 *valid = 1;
341 cond->type = EXPR_UVAL;
342 cond->u.uval = cond->u.ival + (1<<15);
343 break;
344 case EXPR_SVAL:
345 *valid = 0;
346 FIXME("can't deal with string values yet\n");
347 break;
348 default:
349 ERR("Invalid expression type\n");
350 *valid = 0;
351 break;
354 return ERROR_SUCCESS;
357 UINT WHERE_AddCondition( MSIVIEW *view, struct expr *cond )
359 MSIWHEREVIEW *wv = (MSIWHEREVIEW *) view;
360 UINT r, valid = 0;
362 if( wv->view.ops != &where_ops )
363 return ERROR_FUNCTION_FAILED;
364 if( !wv->table )
365 return ERROR_INVALID_PARAMETER;
367 if( !cond )
368 return ERROR_SUCCESS;
370 TRACE("Adding condition\n");
372 r = WHERE_VerifyCondition( wv->table, cond, &valid );
373 if( r != ERROR_SUCCESS )
374 ERR("condition evaluation failed\n");
376 TRACE("condition is %s\n", valid ? "valid" : "invalid" );
377 if( !valid )
379 WHERE_delete_expr( cond );
380 return ERROR_FUNCTION_FAILED;
383 wv->cond = cond;
385 return ERROR_SUCCESS;