ReactOS  0.4.14-dev-323-g6fe6a88
select.c
Go to the documentation of this file.
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002-2004 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 
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"
33 
34 #include "query.h"
35 
37 
38 
39 /* below is the query interface to a table */
40 
41 typedef struct tagMSISELECTVIEW
42 {
48  UINT cols[1];
50 
52 {
54 
55  TRACE("%p %d %d %p\n", sv, row, col, val );
56 
57  if( !sv->table )
58  return ERROR_FUNCTION_FAILED;
59 
60  if( !col || col > sv->num_cols )
61  return ERROR_FUNCTION_FAILED;
62 
63  col = sv->cols[ col - 1 ];
64  if( !col )
65  {
66  *val = 0;
67  return ERROR_SUCCESS;
68  }
69  return sv->table->ops->fetch_int( sv->table, row, col, val );
70 }
71 
72 static UINT SELECT_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
73 {
75 
76  TRACE("%p %d %d %p\n", sv, row, col, stm );
77 
78  if( !sv->table )
79  return ERROR_FUNCTION_FAILED;
80 
81  if( !col || col > sv->num_cols )
82  return ERROR_FUNCTION_FAILED;
83 
84  col = sv->cols[ col - 1 ];
85  if( !col )
86  {
87  *stm = NULL;
88  return ERROR_SUCCESS;
89  }
90  return sv->table->ops->fetch_stream( sv->table, row, col, stm );
91 }
92 
93 static UINT SELECT_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
94 {
96 
97  TRACE("%p %d %p\n", sv, row, rec );
98 
99  if( !sv->table )
100  return ERROR_FUNCTION_FAILED;
101 
102  return msi_view_get_row(sv->db, view, row, rec);
103 }
104 
106 {
108  UINT i, expanded_mask = 0, r = ERROR_SUCCESS, col_count = 0;
109  MSIRECORD *expanded;
110 
111  TRACE("%p %d %p %08x\n", sv, row, rec, mask );
112 
113  if ( !sv->table )
114  return ERROR_FUNCTION_FAILED;
115 
116  /* test if any of the mask bits are invalid */
117  if ( mask >= (1<<sv->num_cols) )
119 
120  /* find the number of columns in the table below */
121  r = sv->table->ops->get_dimensions( sv->table, NULL, &col_count );
122  if( r )
123  return r;
124 
125  /* expand the record to the right size for the underlying table */
126  expanded = MSI_CreateRecord( col_count );
127  if ( !expanded )
128  return ERROR_FUNCTION_FAILED;
129 
130  /* move the right fields across */
131  for ( i=0; i<sv->num_cols; i++ )
132  {
133  r = MSI_RecordCopyField( rec, i+1, expanded, sv->cols[ i ] );
134  if (r != ERROR_SUCCESS)
135  break;
136  expanded_mask |= (1<<(sv->cols[i]-1));
137  }
138 
139  /* set the row in the underlying table */
140  if (r == ERROR_SUCCESS)
141  r = sv->table->ops->set_row( sv->table, row, expanded, expanded_mask );
142 
143  msiobj_release( &expanded->hdr );
144  return r;
145 }
146 
148 {
150  UINT i, table_cols, r;
151  MSIRECORD *outrec;
152 
153  TRACE("%p %p\n", sv, record );
154 
155  if ( !sv->table )
156  return ERROR_FUNCTION_FAILED;
157 
158  /* rearrange the record to suit the table */
159  r = sv->table->ops->get_dimensions( sv->table, NULL, &table_cols );
160  if (r != ERROR_SUCCESS)
161  return r;
162 
163  outrec = MSI_CreateRecord( table_cols + 1 );
164 
165  for (i=0; i<sv->num_cols; i++)
166  {
167  r = MSI_RecordCopyField( record, i+1, outrec, sv->cols[i] );
168  if (r != ERROR_SUCCESS)
169  goto fail;
170  }
171 
172  r = sv->table->ops->insert_row( sv->table, outrec, row, temporary );
173 
174 fail:
175  msiobj_release( &outrec->hdr );
176 
177  return r;
178 }
179 
181 {
183 
184  TRACE("%p %p\n", sv, record);
185 
186  if( !sv->table )
187  return ERROR_FUNCTION_FAILED;
188 
189  return sv->table->ops->execute( sv->table, record );
190 }
191 
192 static UINT SELECT_close( struct tagMSIVIEW *view )
193 {
195 
196  TRACE("%p\n", sv );
197 
198  if( !sv->table )
199  return ERROR_FUNCTION_FAILED;
200 
201  return sv->table->ops->close( sv->table );
202 }
203 
204 static UINT SELECT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
205 {
207 
208  TRACE("%p %p %p\n", sv, rows, cols );
209 
210  if( !sv->table )
211  return ERROR_FUNCTION_FAILED;
212 
213  if( cols )
214  *cols = sv->num_cols;
215 
216  return sv->table->ops->get_dimensions( sv->table, rows, NULL );
217 }
218 
220  UINT *type, BOOL *temporary, LPCWSTR *table_name )
221 {
223 
224  TRACE("%p %d %p %p %p %p\n", sv, n, name, type, temporary, table_name );
225 
226  if( !sv->table )
227  return ERROR_FUNCTION_FAILED;
228 
229  if( !n || n > sv->num_cols )
230  return ERROR_FUNCTION_FAILED;
231 
232  n = sv->cols[ n - 1 ];
233  if( !n )
234  {
235  if (name) *name = szEmpty;
237  if (temporary) *temporary = FALSE;
238  if (table_name) *table_name = szEmpty;
239  return ERROR_SUCCESS;
240  }
241  return sv->table->ops->get_column_info( sv->table, n, name,
242  type, temporary, table_name );
243 }
244 
246 {
248  UINT r, i, num_columns, col, type, val;
249  LPCWSTR str;
250  MSIRECORD *mod;
251 
252  r = SELECT_get_dimensions(view, NULL, &num_columns);
253  if (r != ERROR_SUCCESS)
254  return r;
255 
256  r = sv->table->ops->get_row(sv->table, row - 1, &mod);
257  if (r != ERROR_SUCCESS)
258  return r;
259 
260  for (i = 0; i < num_columns; i++)
261  {
262  col = sv->cols[i];
263 
265  if (r != ERROR_SUCCESS)
266  {
267  ERR("Failed to get column information: %d\n", r);
268  goto done;
269  }
270 
271  if (MSITYPE_IS_BINARY(type))
272  {
273  ERR("Cannot modify binary data!\n");
275  goto done;
276  }
277  else if (type & MSITYPE_STRING)
278  {
279  int len;
280  str = msi_record_get_string( rec, i + 1, &len );
281  r = msi_record_set_string( mod, col, str, len );
282  }
283  else
284  {
285  val = MSI_RecordGetInteger(rec, i + 1);
286  r = MSI_RecordSetInteger(mod, col, val);
287  }
288 
289  if (r != ERROR_SUCCESS)
290  {
291  ERR("Failed to modify record: %d\n", r);
292  goto done;
293  }
294  }
295 
296  r = sv->table->ops->modify(sv->table, MSIMODIFY_UPDATE, mod, row);
297 
298 done:
299  msiobj_release(&mod->hdr);
300  return r;
301 }
302 
303 static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
304  MSIRECORD *rec, UINT row )
305 {
307 
308  TRACE("%p %d %p %d\n", sv, eModifyMode, rec, row );
309 
310  if( !sv->table )
311  return ERROR_FUNCTION_FAILED;
312 
313  if (eModifyMode == MSIMODIFY_UPDATE)
314  return msi_select_update(view, rec, row);
315 
316  return sv->table->ops->modify( sv->table, eModifyMode, rec, row );
317 }
318 
320 {
322 
323  TRACE("%p\n", sv );
324 
325  if( sv->table )
326  sv->table->ops->delete( sv->table );
327  sv->table = NULL;
328 
329  msi_free( sv );
330 
331  return ERROR_SUCCESS;
332 }
333 
336 {
338 
339  TRACE("%p, %d, %u, %p\n", view, col, val, *handle);
340 
341  if( !sv->table )
342  return ERROR_FUNCTION_FAILED;
343 
344  if( (col==0) || (col>sv->num_cols) )
345  return ERROR_FUNCTION_FAILED;
346 
347  col = sv->cols[ col - 1 ];
348 
349  return sv->table->ops->find_matching_rows( sv->table, col, val, row, handle );
350 }
351 
352 
353 static const MSIVIEWOPS select_ops =
354 {
360  NULL,
362  SELECT_close,
368  NULL,
369  NULL,
370  NULL,
371  NULL,
372  NULL,
373  NULL,
374 };
375 
377  LPCWSTR table_name )
378 {
379  UINT r, n;
380  MSIVIEW *table;
381 
382  TRACE("%p adding %s.%s\n", sv, debugstr_w( table_name ),
383  debugstr_w( name ));
384 
385  if( sv->view.ops != &select_ops )
386  return ERROR_FUNCTION_FAILED;
387 
388  table = sv->table;
389  if( !table )
390  return ERROR_FUNCTION_FAILED;
391  if( !table->ops->get_dimensions )
392  return ERROR_FUNCTION_FAILED;
393  if( !table->ops->get_column_info )
394  return ERROR_FUNCTION_FAILED;
395 
396  if( sv->num_cols >= sv->max_cols )
397  return ERROR_FUNCTION_FAILED;
398 
399  if ( !name[0] ) n = 0;
400  else
401  {
402  r = VIEW_find_column( table, name, table_name, &n );
403  if( r != ERROR_SUCCESS )
404  return r;
405  }
406 
407  sv->cols[sv->num_cols] = n;
408  TRACE("Translating column %s from %d -> %d\n",
409  debugstr_w( name ), sv->num_cols, n);
410 
411  sv->num_cols++;
412 
413  return ERROR_SUCCESS;
414 }
415 
416 static int select_count_columns( const column_info *col )
417 {
418  int n;
419  for (n = 0; col; col = col->next)
420  n++;
421  return n;
422 }
423 
425  const column_info *columns )
426 {
427  MSISELECTVIEW *sv = NULL;
428  UINT count = 0, r = ERROR_SUCCESS;
429 
430  TRACE("%p\n", sv );
431 
432  count = select_count_columns( columns );
433 
435  if( !sv )
436  return ERROR_FUNCTION_FAILED;
437 
438  /* fill the structure */
439  sv->view.ops = &select_ops;
440  sv->db = db;
441  sv->table = table;
442  sv->num_cols = 0;
443  sv->max_cols = count;
444 
445  while( columns )
446  {
447  r = SELECT_AddColumn( sv, columns->column, columns->table );
448  if( r )
449  break;
450  columns = columns->next;
451  }
452 
453  if( r == ERROR_SUCCESS )
454  *view = &sv->view;
455  else
456  msi_free( sv );
457 
458  return r;
459 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
UINT max_cols
Definition: select.c:47
static UINT SELECT_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: select.c:72
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:169
#define ERROR_SUCCESS
Definition: deptool.c:10
static UINT SELECT_insert_row(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: select.c:147
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
UINT(* get_dimensions)(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: msipriv.h:281
MSIOBJECTHDR hdr
Definition: msipriv.h:141
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint GLuint GLsizei count
Definition: gl.h:1545
UINT(* find_matching_rows)(struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle)
Definition: msipriv.h:312
GLdouble n
Definition: glext.h:7729
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define MSITYPE_IS_BINARY(type)
Definition: msipriv.h:59
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:5644
struct _column_info * next
Definition: msipriv.h:216
UINT(* execute)(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: msipriv.h:268
#define MSITYPE_STRING
Definition: msipriv.h:47
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1210
static UINT SELECT_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
Definition: select.c:303
#define MSITYPE_UNKNOWN
Definition: msipriv.h:51
struct tagMSISELECTVIEW MSISELECTVIEW
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 MSI_RecordSetInteger(MSIRECORD *, UINT, int) DECLSPEC_HIDDEN
Definition: record.c:328
GLenum GLint GLuint mask
Definition: glext.h:6028
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
UINT cols[1]
Definition: select.c:48
unsigned int BOOL
Definition: ntddk_ex.h:94
#define debugstr_w
Definition: kernel32.h:32
static const MSIVIEWOPS select_ops
Definition: select.c:353
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
LPCWSTR column
Definition: msipriv.h:212
static UINT SELECT_find_matching_rows(struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle)
Definition: select.c:334
GLuint GLfloat * val
Definition: glext.h:7180
UINT num_cols
Definition: select.c:46
static const WCHAR szEmpty[]
Definition: provider.c:50
#define TRACE(s)
Definition: solgame.cpp:4
const MSIVIEWOPS * ops
Definition: msipriv.h:348
UINT(* close)(struct tagMSIVIEW *view)
Definition: msipriv.h:273
WINE_DEFAULT_DEBUG_CHANNEL(msidb)
MSIVIEW view
Definition: select.c:43
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:242
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:79
static UINT SELECT_get_column_info(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: select.c:219
GLenum GLsizei len
Definition: glext.h:6722
MSIVIEW * table
Definition: select.c:45
static UINT SELECT_execute(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: select.c:180
static UINT SELECT_get_row(struct tagMSIVIEW *view, UINT row, MSIRECORD **rec)
Definition: select.c:93
static UINT SELECT_delete(struct tagMSIVIEW *view)
Definition: select.c:319
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:245
const WCHAR * msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN
Definition: record.c:469
#define ERR(fmt,...)
Definition: debug.h:109
UINT(* set_row)(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: msipriv.h:253
UINT(* delete)(struct tagMSIVIEW *)
Definition: msipriv.h:299
static UINT SELECT_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: select.c:105
static int select_count_columns(const column_info *col)
Definition: select.c:416
UINT VIEW_find_column(MSIVIEW *, LPCWSTR, LPCWSTR, UINT *) DECLSPEC_HIDDEN
Definition: msiquery.c:59
static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: select.c:245
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
enum tagMSIMODIFY MSIMODIFY
unsigned int UINT
Definition: ndis.h:50
UINT msi_record_set_string(MSIRECORD *, UINT, const WCHAR *, int) DECLSPEC_HIDDEN
Definition: record.c:625
#define MSITYPE_VALID
Definition: msipriv.h:45
UINT(* fetch_int)(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: msipriv.h:232
UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:287
UINT(* fetch_stream)(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: msipriv.h:240
static BOOL msi_free(void *mem)
Definition: msipriv.h:1227
UINT(* get_row)(struct tagMSIVIEW *view, UINT row, MSIRECORD **rec)
Definition: msipriv.h:246
UINT(* get_column_info)(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: msipriv.h:288
LPCWSTR table
Definition: msipriv.h:211
Definition: name.c:36
UINT(* modify)(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *record, UINT row)
Definition: msipriv.h:294
static UINT SELECT_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: select.c:51
MSIDATABASE * db
Definition: select.c:44
static UINT SELECT_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: select.c:204
UINT SELECT_CreateView(MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table, const column_info *columns)
Definition: select.c:424
static UINT SELECT_AddColumn(MSISELECTVIEW *sv, LPCWSTR name, LPCWSTR table_name)
Definition: select.c:376
static UINT SELECT_close(struct tagMSIVIEW *view)
Definition: select.c:192
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
static int mod
Definition: i386-dis.c:1273
UINT(* insert_row)(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: msipriv.h:258