msi: Cast-qual warning fix.
[wine] / dlls / msi / alter.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2006 Mike McCormack
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
33 #include "query.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(msidb);
36
37 typedef struct tagMSIALTERVIEW
38 {
39     MSIVIEW        view;
40     MSIDATABASE   *db;
41     MSIVIEW       *table;
42     column_info   *colinfo;
43     INT hold;
44 } MSIALTERVIEW;
45
46 static UINT ALTER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
47 {
48     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
49
50     TRACE("%p %d %d %p\n", av, row, col, val );
51
52     return ERROR_FUNCTION_FAILED;
53 }
54
55 static UINT ALTER_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
56 {
57     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
58
59     TRACE("%p %d %d %p\n", av, row, col, stm );
60
61     return ERROR_FUNCTION_FAILED;
62 }
63
64 static UINT ITERATE_columns(MSIRECORD *row, LPVOID param)
65 {
66     (*(UINT *)param)++;
67     return ERROR_SUCCESS;
68 }
69
70 static BOOL check_column_exists(MSIDATABASE *db, MSIVIEW *columns, LPCWSTR table, LPCWSTR column)
71 {
72     MSIQUERY *view;
73     MSIRECORD *rec;
74     UINT r;
75
76     static const WCHAR query[] = {
77         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
78         '`','_','C','o','l','u','m','n','s','`',' ','W','H','E','R','E',' ',
79         '`','T','a','b','l','e','`','=','\'','%','s','\'',' ','A','N','D',' ',
80         '`','N','a','m','e','`','=','\'','%','s','\'',0
81     };
82
83     r = MSI_OpenQuery(db, &view, query, table, column);
84     if (r != ERROR_SUCCESS)
85         return FALSE;
86
87     r = MSI_ViewExecute(view, NULL);
88     if (r != ERROR_SUCCESS)
89         goto done;
90
91     r = MSI_ViewFetch(view, &rec);
92     if (r == ERROR_SUCCESS)
93         msiobj_release(&rec->hdr);
94
95 done:
96     msiobj_release(&view->hdr);
97     return (r == ERROR_SUCCESS);
98 }
99
100 static UINT alter_add_column(MSIALTERVIEW *av)
101 {
102     UINT r, colnum = 1;
103     MSIQUERY *view;
104     MSIVIEW *columns;
105
106     static const WCHAR szColumns[] = {'_','C','o','l','u','m','n','s',0};
107     static const WCHAR query[] = {
108         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
109         '`','_','C','o','l','u','m','n','s','`',' ','W','H','E','R','E',' ',
110         '`','T','a','b','l','e','`','=','\'','%','s','\'',' ','O','R','D','E','R',' ',
111         'B','Y',' ','`','N','u','m','b','e','r','`',0
112     };
113
114     r = TABLE_CreateView(av->db, szColumns, &columns);
115     if (r != ERROR_SUCCESS)
116         return r;
117
118     if (check_column_exists(av->db, columns, av->colinfo->table, av->colinfo->column))
119         return ERROR_BAD_QUERY_SYNTAX;
120
121     r = MSI_OpenQuery(av->db, &view, query, av->colinfo->table, av->colinfo->column);
122     if (r == ERROR_SUCCESS)
123     {
124         r = MSI_IterateRecords(view, NULL, ITERATE_columns, &colnum);
125         msiobj_release(&view->hdr);
126     }
127
128     r = columns->ops->add_column(columns, av->colinfo->table,
129                                  colnum, av->colinfo->column,
130                                  av->colinfo->type, (av->hold == 1));
131
132     msiobj_release(&columns->hdr);
133     return r;
134 }
135
136 static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record )
137 {
138     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
139
140     TRACE("%p %p\n", av, record);
141
142     if (av->hold == 1)
143         av->table->ops->add_ref(av->table);
144     else if (av->hold == -1)
145         av->table->ops->release(av->table);
146
147     if (av->colinfo)
148         return alter_add_column(av);
149
150     return ERROR_SUCCESS;
151 }
152
153 static UINT ALTER_close( struct tagMSIVIEW *view )
154 {
155     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
156
157     TRACE("%p\n", av );
158
159     return ERROR_SUCCESS;
160 }
161
162 static UINT ALTER_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
163 {
164     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
165
166     TRACE("%p %p %p\n", av, rows, cols );
167
168     return ERROR_FUNCTION_FAILED;
169 }
170
171 static UINT ALTER_get_column_info( struct tagMSIVIEW *view,
172                 UINT n, LPWSTR *name, UINT *type )
173 {
174     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
175
176     TRACE("%p %d %p %p\n", av, n, name, type );
177
178     return ERROR_FUNCTION_FAILED;
179 }
180
181 static UINT ALTER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
182                 MSIRECORD *rec )
183 {
184     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
185
186     TRACE("%p %d %p\n", av, eModifyMode, rec );
187
188     return ERROR_FUNCTION_FAILED;
189 }
190
191 static UINT ALTER_delete( struct tagMSIVIEW *view )
192 {
193     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
194
195     TRACE("%p\n", av );
196     msi_free( av );
197     av->table->ops->delete( av->table );
198
199     return ERROR_SUCCESS;
200 }
201
202 static UINT ALTER_find_matching_rows( struct tagMSIVIEW *view, UINT col,
203     UINT val, UINT *row, MSIITERHANDLE *handle )
204 {
205     TRACE("%p, %d, %u, %p\n", view, col, val, *handle);
206
207     return ERROR_FUNCTION_FAILED;
208 }
209
210 static const MSIVIEWOPS alter_ops =
211 {
212     ALTER_fetch_int,
213     ALTER_fetch_stream,
214     NULL,
215     NULL,
216     NULL,
217     ALTER_execute,
218     ALTER_close,
219     ALTER_get_dimensions,
220     ALTER_get_column_info,
221     ALTER_modify,
222     ALTER_delete,
223     ALTER_find_matching_rows,
224     NULL,
225     NULL,
226     NULL,
227     NULL,
228 };
229
230 UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, column_info *colinfo, int hold )
231 {
232     MSIALTERVIEW *av;
233     UINT r;
234
235     TRACE("%p %p %s %d\n", view, colinfo, debugstr_w(name), hold );
236
237     av = msi_alloc_zero( sizeof *av );
238     if( !av )
239         return ERROR_FUNCTION_FAILED;
240
241     r = TABLE_CreateView( db, name, &av->table );
242     if (r != ERROR_SUCCESS || !av->table)
243         return r;
244
245     if (colinfo)
246         colinfo->table = name;
247
248     /* fill the structure */
249     av->view.ops = &alter_ops;
250     av->db = db;
251     av->hold = hold;
252     av->colinfo = colinfo;
253
254     *view = &av->view;
255
256     return ERROR_SUCCESS;
257 }