ReactOS  0.4.15-dev-4853-g3a72a52
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 {
53  UINT r, col_count, i;
55 
56  if ((r = sv->table->ops->get_dimensions( sv->table, NULL, &col_count )))
57  return r;
58 
59  if (!(object = MSI_CreateRecord( col_count )))
60  return ERROR_OUTOFMEMORY;
61 
62  for (i = 0; i < sv->num_cols; i++)
63  {
64  if ((r = MSI_RecordCopyField( in, i + 1, object, sv->cols[i] )))
65  {
66  msiobj_release( &object->hdr );
67  return r;
68  }
69  }
70 
71  *out = object;
72  return ERROR_SUCCESS;
73 }
74 
76 {
78 
79  TRACE("%p %d %d %p\n", sv, row, col, val );
80 
81  if( !sv->table )
82  return ERROR_FUNCTION_FAILED;
83 
84  if( !col || col > sv->num_cols )
85  return ERROR_FUNCTION_FAILED;
86 
87  col = sv->cols[ col - 1 ];
88  if( !col )
89  {
90  *val = 0;
91  return ERROR_SUCCESS;
92  }
93  return sv->table->ops->fetch_int( sv->table, row, col, val );
94 }
95 
96 static UINT SELECT_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
97 {
99 
100  TRACE("%p %d %d %p\n", sv, row, col, stm );
101 
102  if( !sv->table )
103  return ERROR_FUNCTION_FAILED;
104 
105  if( !col || col > sv->num_cols )
106  return ERROR_FUNCTION_FAILED;
107 
108  col = sv->cols[ col - 1 ];
109  if( !col )
110  {
111  *stm = NULL;
112  return ERROR_SUCCESS;
113  }
114  return sv->table->ops->fetch_stream( sv->table, row, col, stm );
115 }
116 
118 {
120  UINT i, expanded_mask = 0, r = ERROR_SUCCESS, col_count = 0;
121  MSIRECORD *expanded;
122 
123  TRACE("%p %d %p %08x\n", sv, row, rec, mask );
124 
125  if ( !sv->table )
126  return ERROR_FUNCTION_FAILED;
127 
128  /* test if any of the mask bits are invalid */
129  if ( mask >= (1<<sv->num_cols) )
131 
132  /* find the number of columns in the table below */
133  r = sv->table->ops->get_dimensions( sv->table, NULL, &col_count );
134  if( r )
135  return r;
136 
137  /* expand the record to the right size for the underlying table */
138  expanded = MSI_CreateRecord( col_count );
139  if ( !expanded )
140  return ERROR_FUNCTION_FAILED;
141 
142  /* move the right fields across */
143  for ( i=0; i<sv->num_cols; i++ )
144  {
145  r = MSI_RecordCopyField( rec, i+1, expanded, sv->cols[ i ] );
146  if (r != ERROR_SUCCESS)
147  break;
148  expanded_mask |= (1<<(sv->cols[i]-1));
149  }
150 
151  /* set the row in the underlying table */
152  if (r == ERROR_SUCCESS)
153  r = sv->table->ops->set_row( sv->table, row, expanded, expanded_mask );
154 
155  msiobj_release( &expanded->hdr );
156  return r;
157 }
158 
160 {
162  UINT table_cols, r;
163  MSIRECORD *outrec;
164 
165  TRACE("%p %p\n", sv, record );
166 
167  if ( !sv->table )
168  return ERROR_FUNCTION_FAILED;
169 
170  /* rearrange the record to suit the table */
171  r = sv->table->ops->get_dimensions( sv->table, NULL, &table_cols );
172  if (r != ERROR_SUCCESS)
173  return r;
174 
175  if ((r = translate_record( sv, record, &outrec )))
176  return r;
177 
178  r = sv->table->ops->insert_row( sv->table, outrec, row, temporary );
179 
180  msiobj_release( &outrec->hdr );
181  return r;
182 }
183 
185 {
187 
188  TRACE("%p %p\n", sv, record);
189 
190  if( !sv->table )
191  return ERROR_FUNCTION_FAILED;
192 
193  return sv->table->ops->execute( sv->table, record );
194 }
195 
196 static UINT SELECT_close( struct tagMSIVIEW *view )
197 {
199 
200  TRACE("%p\n", sv );
201 
202  if( !sv->table )
203  return ERROR_FUNCTION_FAILED;
204 
205  return sv->table->ops->close( sv->table );
206 }
207 
208 static UINT SELECT_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
209 {
211 
212  TRACE("%p %p %p\n", sv, rows, cols );
213 
214  if( !sv->table )
215  return ERROR_FUNCTION_FAILED;
216 
217  if( cols )
218  *cols = sv->num_cols;
219 
220  return sv->table->ops->get_dimensions( sv->table, rows, NULL );
221 }
222 
224  UINT *type, BOOL *temporary, LPCWSTR *table_name )
225 {
227 
228  TRACE("%p %d %p %p %p %p\n", sv, n, name, type, temporary, table_name );
229 
230  if( !sv->table )
231  return ERROR_FUNCTION_FAILED;
232 
233  if( !n || n > sv->num_cols )
234  return ERROR_FUNCTION_FAILED;
235 
236  n = sv->cols[ n - 1 ];
237  if( !n )
238  {
239  if (name) *name = L"";
241  if (temporary) *temporary = FALSE;
242  if (table_name) *table_name = L"";
243  return ERROR_SUCCESS;
244  }
245  return sv->table->ops->get_column_info( sv->table, n, name,
246  type, temporary, table_name );
247 }
248 
250 {
252  UINT r, i, col, type, val;
253  IStream *stream;
254  LPCWSTR str;
255 
256  for (i = 0; i < sv->num_cols; i++)
257  {
258  col = sv->cols[i];
259 
261  if (r != ERROR_SUCCESS)
262  {
263  ERR("Failed to get column information: %d\n", r);
264  return r;
265  }
266 
267  if (MSITYPE_IS_BINARY(type))
268  {
269  if (MSI_RecordGetIStream(rec, i + 1, &stream))
270  return ERROR_FUNCTION_FAILED;
271  r = sv->table->ops->set_stream(sv->table, row, col, stream);
272  }
273  else if (type & MSITYPE_STRING)
274  {
275  int len;
276  str = msi_record_get_string(rec, i + 1, &len);
277  r = sv->table->ops->set_string(sv->table, row, col, str, len);
278  }
279  else
280  {
281  val = MSI_RecordGetInteger(rec, i + 1);
282  r = sv->table->ops->set_int(sv->table, row, col, val);
283  }
284 
285  if (r != ERROR_SUCCESS)
286  {
287  ERR("Failed to modify record: %d\n", r);
288  return r;
289  }
290  }
291 
292  return ERROR_SUCCESS;
293 }
294 
296  MSIRECORD *rec, UINT row )
297 {
299  MSIRECORD *table_rec;
300  UINT r;
301 
302  TRACE("view %p, mode %d, rec %p, row %u.\n", view, mode, rec, row);
303 
304  if( !sv->table )
305  return ERROR_FUNCTION_FAILED;
306 
307  /* Tests demonstrate that UPDATE only affects the columns selected and that
308  * others are left unchanged; however, ASSIGN overwrites unselected columns
309  * to NULL. Similarly, MERGE matches all unselected columns as NULL rather
310  * than just ignoring them. */
311 
312  switch (mode)
313  {
314  case MSIMODIFY_REFRESH:
315  return msi_view_refresh_row(sv->db, view, row, rec);
316  case MSIMODIFY_UPDATE:
317  return msi_select_update(view, rec, row);
318  case MSIMODIFY_INSERT:
319  case MSIMODIFY_ASSIGN:
320  case MSIMODIFY_MERGE:
323  if ((r = translate_record( sv, rec, &table_rec )))
324  return r;
325 
326  r = sv->table->ops->modify( sv->table, mode, table_rec, row );
327  msiobj_release( &table_rec->hdr );
328  return r;
329  case MSIMODIFY_DELETE:
330  return sv->table->ops->modify( sv->table, mode, rec, row );
331  default:
332  FIXME("unhandled mode %d\n", mode);
333  return ERROR_FUNCTION_FAILED;
334  }
335 }
336 
338 {
340 
341  TRACE("%p\n", sv );
342 
343  if( sv->table )
344  sv->table->ops->delete( sv->table );
345  sv->table = NULL;
346 
347  msi_free( sv );
348 
349  return ERROR_SUCCESS;
350 }
351 
352 static const MSIVIEWOPS select_ops =
353 {
356  NULL,
357  NULL,
358  NULL,
361  NULL,
363  SELECT_close,
368  NULL,
369  NULL,
370  NULL,
371  NULL,
372  NULL,
373 };
374 
376  LPCWSTR table_name )
377 {
378  UINT r, n;
379  MSIVIEW *table;
380 
381  TRACE("%p adding %s.%s\n", sv, debugstr_w( table_name ),
382  debugstr_w( name ));
383 
384  if( sv->view.ops != &select_ops )
385  return ERROR_FUNCTION_FAILED;
386 
387  table = sv->table;
388  if( !table )
389  return ERROR_FUNCTION_FAILED;
390  if( !table->ops->get_dimensions )
391  return ERROR_FUNCTION_FAILED;
392  if( !table->ops->get_column_info )
393  return ERROR_FUNCTION_FAILED;
394 
395  if( sv->num_cols >= sv->max_cols )
396  return ERROR_FUNCTION_FAILED;
397 
398  if ( !name[0] ) n = 0;
399  else
400  {
401  r = VIEW_find_column( table, name, table_name, &n );
402  if( r != ERROR_SUCCESS )
403  return r;
404  }
405 
406  sv->cols[sv->num_cols] = n;
407  TRACE("Translating column %s from %d -> %d\n",
408  debugstr_w( name ), sv->num_cols, n);
409 
410  sv->num_cols++;
411 
412  return ERROR_SUCCESS;
413 }
414 
415 static int select_count_columns( const column_info *col )
416 {
417  int n;
418  for (n = 0; col; col = col->next)
419  n++;
420  return n;
421 }
422 
424  const column_info *columns )
425 {
426  MSISELECTVIEW *sv = NULL;
427  UINT count = 0, r = ERROR_SUCCESS;
428 
429  TRACE("%p\n", sv );
430 
431  count = select_count_columns( columns );
432 
434  if( !sv )
435  return ERROR_FUNCTION_FAILED;
436 
437  /* fill the structure */
438  sv->view.ops = &select_ops;
439  sv->db = db;
440  sv->table = table;
441  sv->num_cols = 0;
442  sv->max_cols = count;
443 
444  while( columns )
445  {
446  r = SELECT_AddColumn( sv, columns->column, columns->table );
447  if( r )
448  break;
449  columns = columns->next;
450  }
451 
452  if( r == ERROR_SUCCESS )
453  *view = &sv->view;
454  else
455  msi_free( sv );
456 
457  return r;
458 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
UINT max_cols
Definition: select.c:47
static UINT SELECT_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: select.c:96
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:166
UINT(* set_stream)(struct tagMSIVIEW *view, UINT row, UINT col, IStream *stream)
Definition: msipriv.h:271
#define ERROR_SUCCESS
Definition: deptool.c:10
static UINT SELECT_insert_row(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: select.c:159
coclass MSXML2::XSLTemplate40 object
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
UINT(* get_dimensions)(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: msipriv.h:306
MSIOBJECTHDR hdr
Definition: msipriv.h:151
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint GLuint GLsizei count
Definition: gl.h:1545
UINT MSI_RecordGetIStream(MSIRECORD *, UINT, IStream **) DECLSPEC_HIDDEN
Definition: record.c:852
GLdouble n
Definition: glext.h:7729
#define MSITYPE_IS_BINARY(type)
Definition: msipriv.h:62
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:5644
struct _column_info * next
Definition: msipriv.h:226
static void msi_free(void *mem)
Definition: msipriv.h:1159
UINT(* execute)(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: msipriv.h:293
#define MSITYPE_STRING
Definition: msipriv.h:50
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
#define MSITYPE_UNKNOWN
Definition: msipriv.h:54
struct tagMSISELECTVIEW MSISELECTVIEW
#define L(x)
Definition: ntvdm.h:50
GLenum GLint GLuint mask
Definition: glext.h:6028
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
#define FALSE
Definition: types.h:117
UINT cols[1]
Definition: select.c:48
unsigned int BOOL
Definition: ntddk_ex.h:94
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:111
UINT(* set_string)(struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
Definition: msipriv.h:264
static const MSIVIEWOPS select_ops
Definition: select.c:352
const WCHAR * str
LPCWSTR column
Definition: msipriv.h:223
int MSIMODIFY
Definition: winemsi.idl:33
static UINT SELECT_modify(struct tagMSIVIEW *view, MSIMODIFY mode, MSIRECORD *rec, UINT row)
Definition: select.c:295
GLuint GLfloat * val
Definition: glext.h:7180
UINT msi_view_refresh_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD *rec)
Definition: msiquery.c:287
UINT num_cols
Definition: select.c:46
#define TRACE(s)
Definition: solgame.cpp:4
const MSIVIEWOPS * ops
Definition: msipriv.h:355
static FILE * out
Definition: regtests2xml.c:44
UINT(* close)(struct tagMSIVIEW *view)
Definition: msipriv.h:298
WINE_DEFAULT_DEBUG_CHANNEL(msidb)
MSIVIEW view
Definition: select.c:43
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
static UINT SELECT_get_column_info(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: select.c:223
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:184
GLenum mode
Definition: glext.h:6217
static UINT SELECT_delete(struct tagMSIVIEW *view)
Definition: select.c:337
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
const WCHAR * msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN
Definition: record.c:420
#define ERR(fmt,...)
Definition: debug.h:110
UINT msi_select_update(MSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: select.c:249
UINT(* set_row)(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: msipriv.h:278
UINT(* delete)(struct tagMSIVIEW *)
Definition: msipriv.h:324
UINT(* set_int)(struct tagMSIVIEW *view, UINT row, UINT col, int val)
Definition: msipriv.h:257
static UINT SELECT_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: select.c:117
static int select_count_columns(const column_info *col)
Definition: select.c:415
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
GLuint in
Definition: glext.h:9616
UINT VIEW_find_column(MSIVIEW *, LPCWSTR, LPCWSTR, UINT *) DECLSPEC_HIDDEN
Definition: msiquery.c:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
#define MSITYPE_VALID
Definition: msipriv.h:48
UINT(* fetch_int)(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: msipriv.h:242
static UINT translate_record(MSISELECTVIEW *sv, MSIRECORD *in, MSIRECORD **out)
Definition: select.c:51
UINT(* fetch_stream)(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: msipriv.h:250
UINT(* get_column_info)(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: msipriv.h:313
LPCWSTR table
Definition: msipriv.h:222
Definition: name.c:38
UINT(* modify)(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *record, UINT row)
Definition: msipriv.h:319
static UINT SELECT_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: select.c:75
MSIDATABASE * db
Definition: select.c:44
static UINT SELECT_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: select.c:208
UINT SELECT_CreateView(MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table, const column_info *columns)
Definition: select.c:423
static UINT SELECT_AddColumn(MSISELECTVIEW *sv, LPCWSTR name, LPCWSTR table_name)
Definition: select.c:375
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
static UINT SELECT_close(struct tagMSIVIEW *view)
Definition: select.c:196
#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
UINT(* insert_row)(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: msipriv.h:283