ReactOS 0.4.15-dev-8058-ga7cbb60
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
41typedef struct tagMSISELECTVIEW
42{
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 )
83
84 if( !col || col > sv->num_cols )
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
97{
99
100 TRACE("%p %d %d %p\n", sv, row, col, stm );
101
102 if( !sv->table )
104
105 if( !col || col > sv->num_cols )
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 )
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 )
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 )
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 )
192
193 return sv->table->ops->execute( sv->table, record );
194}
195
197{
199
200 TRACE("%p\n", sv );
201
202 if( !sv->table )
204
205 return sv->table->ops->close( sv->table );
206}
207
208static 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 )
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 )
232
233 if( !n || n > sv->num_cols )
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;
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
268 {
269 if (MSI_RecordGetIStream(rec, i + 1, &stream))
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 )
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 {
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);
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
352static const MSIVIEWOPS select_ops =
353{
356 NULL,
357 NULL,
358 NULL,
361 NULL,
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 )
386
387 table = sv->table;
388 if( !table )
390 if( !table->ops->get_dimensions )
392 if( !table->ops->get_column_info )
394
395 if( sv->num_cols >= sv->max_cols )
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
415static 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 )
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 WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: debug.h:114
#define ERR(fmt,...)
Definition: debug.h:113
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
static UINT SELECT_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: select.c:208
static UINT SELECT_close(struct tagMSIVIEW *view)
Definition: select.c:196
UINT msi_select_update(MSIVIEW *view, MSIRECORD *rec, UINT row)
Definition: select.c:249
static const MSIVIEWOPS select_ops
Definition: select.c:352
static UINT SELECT_execute(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: select.c:184
struct tagMSISELECTVIEW MSISELECTVIEW
static UINT SELECT_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: select.c:75
static UINT SELECT_insert_row(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: select.c:159
static UINT translate_record(MSISELECTVIEW *sv, MSIRECORD *in, MSIRECORD **out)
Definition: select.c:51
static UINT SELECT_modify(struct tagMSIVIEW *view, MSIMODIFY mode, MSIRECORD *rec, UINT row)
Definition: select.c:295
UINT SELECT_CreateView(MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table, const column_info *columns)
Definition: select.c:423
static UINT SELECT_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: select.c:96
static UINT SELECT_get_column_info(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: select.c:223
static UINT SELECT_delete(struct tagMSIVIEW *view)
Definition: select.c:337
static UINT SELECT_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: select.c:117
static UINT SELECT_AddColumn(MSISELECTVIEW *sv, LPCWSTR name, LPCWSTR table_name)
Definition: select.c:375
static int select_count_columns(const column_info *col)
Definition: select.c:415
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
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble n
Definition: glext.h:7729
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum mode
Definition: glext.h:6217
GLuint in
Definition: glext.h:9616
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
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
#define debugstr_w
Definition: kernel32.h:32
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
UINT MSI_RecordGetIStream(MSIRECORD *, UINT, IStream **) DECLSPEC_HIDDEN
Definition: record.c:852
#define MSITYPE_VALID
Definition: msipriv.h:48
static void msi_free(void *mem)
Definition: msipriv.h:1159
#define MSITYPE_IS_BINARY(type)
Definition: msipriv.h:62
const WCHAR * msi_record_get_string(const MSIRECORD *, UINT, int *) DECLSPEC_HIDDEN
Definition: record.c:420
#define MSITYPE_STRING
Definition: msipriv.h:50
int MSI_RecordGetInteger(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:213
UINT VIEW_find_column(MSIVIEW *, LPCWSTR, LPCWSTR, UINT *) DECLSPEC_HIDDEN
Definition: msiquery.c:59
#define MSITYPE_UNKNOWN
Definition: msipriv.h:54
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
UINT MSI_RecordCopyField(MSIRECORD *, UINT, MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:166
UINT msi_view_refresh_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD *rec)
Definition: msiquery.c:287
@ MSIMODIFY_DELETE
Definition: msiquery.h:57
@ MSIMODIFY_MERGE
Definition: msiquery.h:56
@ MSIMODIFY_INSERT_TEMPORARY
Definition: msiquery.h:58
@ MSIMODIFY_UPDATE
Definition: msiquery.h:53
@ MSIMODIFY_ASSIGN
Definition: msiquery.h:54
@ MSIMODIFY_VALIDATE_NEW
Definition: msiquery.h:60
@ MSIMODIFY_INSERT
Definition: msiquery.h:52
@ MSIMODIFY_REFRESH
Definition: msiquery.h:51
unsigned int UINT
Definition: ndis.h:50
#define L(x)
Definition: ntvdm.h:50
static FILE * out
Definition: regtests2xml.c:44
const WCHAR * str
#define TRACE(s)
Definition: solgame.cpp:4
struct _column_info * next
Definition: msipriv.h:226
LPCWSTR column
Definition: msipriv.h:223
LPCWSTR table
Definition: msipriv.h:222
Definition: name.c:39
Definition: parse.h:23
MSIOBJECTHDR hdr
Definition: msipriv.h:151
UINT max_cols
Definition: select.c:47
UINT cols[1]
Definition: select.c:48
MSIVIEW view
Definition: select.c:43
MSIVIEW * table
Definition: select.c:45
MSIDATABASE * db
Definition: select.c:44
UINT num_cols
Definition: select.c:46
UINT(* insert_row)(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: msipriv.h:283
UINT(* set_row)(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
Definition: msipriv.h:278
UINT(* set_stream)(struct tagMSIVIEW *view, UINT row, UINT col, IStream *stream)
Definition: msipriv.h:271
UINT(* fetch_int)(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
Definition: msipriv.h:242
UINT(* set_string)(struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len)
Definition: msipriv.h:264
UINT(* fetch_stream)(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
Definition: msipriv.h:250
UINT(* modify)(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *record, UINT row)
Definition: msipriv.h:319
UINT(* close)(struct tagMSIVIEW *view)
Definition: msipriv.h:298
UINT(* get_dimensions)(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
Definition: msipriv.h:306
UINT(* execute)(struct tagMSIVIEW *view, MSIRECORD *record)
Definition: msipriv.h:293
UINT(* get_column_info)(struct tagMSIVIEW *view, UINT n, LPCWSTR *name, UINT *type, BOOL *temporary, LPCWSTR *table_name)
Definition: msipriv.h:313
UINT(* set_int)(struct tagMSIVIEW *view, UINT row, UINT col, int val)
Definition: msipriv.h:257
UINT(* delete)(struct tagMSIVIEW *)
Definition: msipriv.h:324
const MSIVIEWOPS * ops
Definition: msipriv.h:355
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int MSIMODIFY
Definition: winemsi.idl:33
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185