* Sync up to trunk head (r64921).
[reactos.git] / dll / win32 / msi / update.c
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 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 "msipriv.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(msidb);
24
25 /* below is the query interface to a table */
26
27 typedef struct tagMSIUPDATEVIEW
28 {
29 MSIVIEW view;
30 MSIDATABASE *db;
31 MSIVIEW *wv;
32 column_info *vals;
33 } MSIUPDATEVIEW;
34
35 static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
36 {
37 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
38
39 TRACE("%p %d %d %p\n", uv, row, col, val );
40
41 return ERROR_FUNCTION_FAILED;
42 }
43
44 static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
45 {
46 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
47 UINT i, r, col_count = 0, row_count = 0;
48 MSIRECORD *values = NULL;
49 MSIRECORD *where = NULL;
50 MSIVIEW *wv;
51 UINT cols_count, where_count;
52 column_info *col = uv->vals;
53
54 TRACE("%p %p\n", uv, record );
55
56 /* extract the where markers from the record */
57 if (record)
58 {
59 r = MSI_RecordGetFieldCount(record);
60
61 for (i = 0; col; col = col->next)
62 i++;
63
64 cols_count = i;
65 where_count = r - i;
66
67 if (where_count > 0)
68 {
69 where = MSI_CreateRecord(where_count);
70
71 if (where)
72 for (i = 1; i <= where_count; i++)
73 MSI_RecordCopyField(record, cols_count + i, where, i);
74 }
75 }
76
77 wv = uv->wv;
78 if( !wv )
79 {
80 r = ERROR_FUNCTION_FAILED;
81 goto done;
82 }
83
84 r = wv->ops->execute( wv, where );
85 TRACE("tv execute returned %x\n", r);
86 if( r )
87 goto done;
88
89 r = wv->ops->get_dimensions( wv, &row_count, &col_count );
90 if( r )
91 goto done;
92
93 values = msi_query_merge_record( col_count, uv->vals, record );
94 if (!values)
95 {
96 r = ERROR_FUNCTION_FAILED;
97 goto done;
98 }
99
100 for ( i=0; i<row_count; i++ )
101 {
102 r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 );
103 if (r != ERROR_SUCCESS)
104 break;
105 }
106
107 done:
108 if ( where ) msiobj_release( &where->hdr );
109 if ( values ) msiobj_release( &values->hdr );
110
111 return r;
112 }
113
114
115 static UINT UPDATE_close( struct tagMSIVIEW *view )
116 {
117 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
118 MSIVIEW *wv;
119
120 TRACE("%p\n", uv);
121
122 wv = uv->wv;
123 if( !wv )
124 return ERROR_FUNCTION_FAILED;
125
126 return wv->ops->close( wv );
127 }
128
129 static UINT UPDATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
130 {
131 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
132 MSIVIEW *wv;
133
134 TRACE("%p %p %p\n", uv, rows, cols );
135
136 wv = uv->wv;
137 if( !wv )
138 return ERROR_FUNCTION_FAILED;
139
140 return wv->ops->get_dimensions( wv, rows, cols );
141 }
142
143 static UINT UPDATE_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name,
144 UINT *type, BOOL *temporary, LPCWSTR *table_name )
145 {
146 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
147 MSIVIEW *wv;
148
149 TRACE("%p %d %p %p %p %p\n", uv, n, name, type, temporary, table_name );
150
151 wv = uv->wv;
152 if( !wv )
153 return ERROR_FUNCTION_FAILED;
154
155 return wv->ops->get_column_info( wv, n, name, type, temporary, table_name );
156 }
157
158 static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
159 MSIRECORD *rec, UINT row )
160 {
161 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
162
163 TRACE("%p %d %p\n", uv, eModifyMode, rec );
164
165 return ERROR_FUNCTION_FAILED;
166 }
167
168 static UINT UPDATE_delete( struct tagMSIVIEW *view )
169 {
170 MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
171 MSIVIEW *wv;
172
173 TRACE("%p\n", uv );
174
175 wv = uv->wv;
176 if( wv )
177 wv->ops->delete( wv );
178 msiobj_release( &uv->db->hdr );
179 msi_free( uv );
180
181 return ERROR_SUCCESS;
182 }
183
184 static UINT UPDATE_find_matching_rows( struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle )
185 {
186 TRACE("%p %d %d %p\n", view, col, val, *handle );
187
188 return ERROR_FUNCTION_FAILED;
189 }
190
191
192 static const MSIVIEWOPS update_ops =
193 {
194 UPDATE_fetch_int,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199 NULL,
200 UPDATE_execute,
201 UPDATE_close,
202 UPDATE_get_dimensions,
203 UPDATE_get_column_info,
204 UPDATE_modify,
205 UPDATE_delete,
206 UPDATE_find_matching_rows,
207 NULL,
208 NULL,
209 NULL,
210 NULL,
211 NULL,
212 };
213
214 UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
215 column_info *columns, struct expr *expr )
216 {
217 MSIUPDATEVIEW *uv = NULL;
218 UINT r;
219 MSIVIEW *sv = NULL, *wv = NULL;
220
221 TRACE("%p\n", uv );
222
223 if (expr)
224 r = WHERE_CreateView( db, &wv, table, expr );
225 else
226 r = TABLE_CreateView( db, table, &wv );
227
228 if( r != ERROR_SUCCESS )
229 return r;
230
231 /* then select the columns we want */
232 r = SELECT_CreateView( db, &sv, wv, columns );
233 if( r != ERROR_SUCCESS )
234 {
235 wv->ops->delete( wv );
236 return r;
237 }
238
239 uv = msi_alloc_zero( sizeof *uv );
240 if( !uv )
241 {
242 wv->ops->delete( wv );
243 return ERROR_FUNCTION_FAILED;
244 }
245
246 /* fill the structure */
247 uv->view.ops = &update_ops;
248 msiobj_addref( &db->hdr );
249 uv->db = db;
250 uv->vals = columns;
251 uv->wv = sv;
252 *view = (MSIVIEW*) uv;
253
254 return ERROR_SUCCESS;
255 }