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