Fix the case of product and company names.
[wine] / dlls / msi / msiquery.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
36 WINE_DEFAULT_DEBUG_CHANNEL(msi);
37
38 typedef struct tagMSIQUERY
39 {
40     MSIVIEW *view;
41     UINT row;
42     MSIDATABASE *db;
43 } MSIQUERY;
44
45 UINT WINAPI MsiDatabaseIsTablePersistentA(
46               MSIHANDLE hDatabase, LPSTR szTableName)
47 {
48     FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName));
49     return ERROR_CALL_NOT_IMPLEMENTED;
50 }
51
52 UINT WINAPI MsiDatabaseIsTablePersistentW(
53               MSIHANDLE hDatabase, LPWSTR szTableName)
54 {
55     FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName));
56     return ERROR_CALL_NOT_IMPLEMENTED;
57 }
58
59 void MSI_CloseView( VOID *arg )
60 {
61     MSIQUERY *query = arg;
62
63     if( query->view && query->view->ops->delete )
64         query->view->ops->delete( query->view );
65 }
66
67 UINT VIEW_find_column( MSIVIEW *table, LPWSTR name, UINT *n )
68 {
69     LPWSTR col_name;
70     UINT i, count, r;
71
72     r = table->ops->get_dimensions( table, NULL, &count );
73     if( r != ERROR_SUCCESS )
74         return r;
75
76     for( i=1; i<=count; i++ )
77     {
78         INT x;
79
80         col_name = NULL;
81         r = table->ops->get_column_info( table, i, &col_name, NULL );
82         if( r != ERROR_SUCCESS )
83             return r;
84         x = lstrcmpW( name, col_name );
85         HeapFree( GetProcessHeap(), 0, col_name );
86         if( !x )
87         {
88             *n = i;
89             return ERROR_SUCCESS;
90         }
91     }
92
93     return ERROR_INVALID_PARAMETER;
94 }
95
96 UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
97               LPCSTR szQuery, MSIHANDLE *phView)
98 {
99     UINT r;
100     LPCWSTR szwQuery;
101
102     TRACE("%ld %s %p\n", hdb, debugstr_a(szQuery), phView);
103
104     if( szQuery )
105     {
106         szwQuery = HEAP_strdupAtoW( GetProcessHeap(), 0, szQuery );
107         if( !szwQuery )
108             return ERROR_FUNCTION_FAILED;
109     }
110     else
111         szwQuery = NULL;
112
113     r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
114
115     return r;
116 }
117
118 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
119               LPCWSTR szQuery, MSIHANDLE *phView)
120 {
121     MSIDATABASE *db;
122     MSIHANDLE handle;
123     MSIQUERY *query;
124     UINT r;
125
126     TRACE("%s %p\n", debugstr_w(szQuery), phView);
127
128     if( !szQuery)
129         return ERROR_INVALID_PARAMETER;
130
131     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
132     if( !db )
133         return ERROR_INVALID_HANDLE;
134
135     /* pre allocate a handle to hold a pointer to the view */
136     handle = alloc_msihandle( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY), MSI_CloseView );
137     if( !handle )
138         return ERROR_FUNCTION_FAILED;
139     query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
140     if( !query )
141         return ERROR_FUNCTION_FAILED;
142
143     query->row = 0;
144     query->db = db;
145     query->view = NULL;
146
147     r = MSI_ParseSQL( db, szQuery, &query->view );
148     if( r != ERROR_SUCCESS )
149     {
150         MsiCloseHandle( handle );
151         return r;
152     }
153
154     *phView = handle;
155
156     return ERROR_SUCCESS;
157 }
158
159 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
160 {
161     MSIQUERY *query;
162     MSIVIEW *view;
163     MSIHANDLE handle;
164     UINT row_count = 0, col_count = 0, i, ival, ret, type;
165
166     TRACE("%ld %p\n", hView, record);
167
168     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
169     if( !query )
170         return ERROR_INVALID_HANDLE;
171     view = query->view;
172     if( !view )
173         return ERROR_FUNCTION_FAILED;
174
175     ret = view->ops->get_dimensions( view, &row_count, &col_count );
176     if( ret )
177         return ret;
178     if( !col_count )
179         return ERROR_INVALID_PARAMETER;
180
181     if( query->row >= row_count )
182         return ERROR_NO_MORE_ITEMS;
183
184     handle = MsiCreateRecord( col_count );
185     if( !handle )
186         return ERROR_FUNCTION_FAILED;
187
188     for( i=1; i<=col_count; i++ )
189     {
190         ret = view->ops->get_column_info( view, i, NULL, &type );
191         if( ret )
192         {
193             ERR("Error getting column type for %d\n", i );
194             continue;
195         }
196         ret = view->ops->fetch_int( view, query->row, i, &ival );
197         if( ret )
198         {
199             ERR("Error fetching data for %d\n", i );
200             continue;
201         }
202         if( ! (type & MSITYPE_VALID ) )
203             ERR("Invalid type!\n");
204
205         /* check if it's nul (0) - if so, don't set anything */
206         if( !ival )
207             continue;
208
209         if( type & MSITYPE_STRING )
210         {
211             LPWSTR sval = MSI_makestring( query->db, ival );
212             MsiRecordSetStringW( handle, i, sval );
213             HeapFree( GetProcessHeap(), 0, sval );
214         }
215         else
216         {
217             if( (type & MSI_DATASIZEMASK) == 2 )
218                 MsiRecordSetInteger( handle, i, ival - (1<<15) );
219             else
220                 MsiRecordSetInteger( handle, i, ival - (1<<31) );
221         }
222     }
223     query->row ++;
224
225     *record = handle;
226
227     return ERROR_SUCCESS;
228 }
229
230 UINT WINAPI MsiViewClose(MSIHANDLE hView)
231 {
232     MSIQUERY *query;
233     MSIVIEW *view;
234
235     TRACE("%ld\n", hView );
236
237     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
238     if( !query )
239         return ERROR_INVALID_HANDLE;
240
241     view = query->view;
242     if( !view )
243         return ERROR_FUNCTION_FAILED;
244     if( !view->ops->close )
245         return ERROR_FUNCTION_FAILED;
246
247     return view->ops->close( view );
248 }
249
250 UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
251 {
252     MSIQUERY *query;
253     MSIVIEW *view;
254
255     TRACE("%ld %ld\n", hView, hRec);
256
257     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
258     if( !query )
259         return ERROR_INVALID_HANDLE;
260
261     view = query->view;
262     if( !view )
263         return ERROR_FUNCTION_FAILED;
264     if( !view->ops->execute )
265         return ERROR_FUNCTION_FAILED;
266     query->row = 0;
267
268     return view->ops->execute( view, hRec );
269 }
270
271 UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
272 {
273     MSIVIEW *view;
274     MSIQUERY *query;
275     MSIHANDLE handle;
276     UINT ret, i, count = 0, type;
277     LPWSTR name;
278
279     TRACE("%ld %d %p\n", hView, info, hRec);
280
281     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
282     if( !query )
283         return ERROR_INVALID_HANDLE;
284
285     view = query->view;
286     if( !view )
287         return ERROR_FUNCTION_FAILED;
288
289     if( !view->ops->get_dimensions )
290         return ERROR_FUNCTION_FAILED;
291
292     ret = view->ops->get_dimensions( view, NULL, &count );
293     if( ret )
294         return ret;
295     if( !count )
296         return ERROR_INVALID_PARAMETER;
297
298     handle = MsiCreateRecord( count );
299     if( !handle )
300         return ERROR_FUNCTION_FAILED;
301
302     for( i=0; i<count; i++ )
303     {
304         name = NULL;
305         ret = view->ops->get_column_info( view, i+1, &name, &type );
306         if( ret != ERROR_SUCCESS )
307             continue;
308         MsiRecordSetStringW( handle, i+1, name );
309         HeapFree( GetProcessHeap(), 0, name );
310     }
311
312     *hRec = handle;
313
314     return ERROR_SUCCESS;
315 }
316
317
318 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
319 {
320     FIXME("%ld %s\n", hInstall, debugstr_a(szAction) );
321     return ERROR_CALL_NOT_IMPLEMENTED;
322 }
323
324 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
325 {
326     FIXME("%ld %s\n", hInstall, debugstr_w(szAction) );
327     return ERROR_CALL_NOT_IMPLEMENTED;
328 }
329
330 UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb, 
331                  LPCSTR szTransformFile, int iErrorCond)
332 {
333     FIXME("%ld %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
334     return ERROR_CALL_NOT_IMPLEMENTED;
335 }
336
337 UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb, 
338                  LPCWSTR szTransformFile, int iErrorCond)
339 {
340     FIXME("%ld %s %d\n", hdb, debugstr_w(szTransformFile), iErrorCond);
341     return ERROR_CALL_NOT_IMPLEMENTED;
342 }
343
344 UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
345                  LPCSTR szTransformFile, int iReserved1, int iReserved2 )
346 {
347     FIXME("%ld %ld %s %d %d\n", hdb, hdbref, 
348            debugstr_a(szTransformFile), iReserved1, iReserved2);
349     return ERROR_CALL_NOT_IMPLEMENTED;
350 }
351
352 UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
353                  LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
354 {
355     FIXME("%ld %ld %s %d %d\n", hdb, hdbref, 
356            debugstr_w(szTransformFile), iReserved1, iReserved2);
357     return ERROR_CALL_NOT_IMPLEMENTED;
358 }
359
360 UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
361 {
362     FIXME("%ld\n", hdb);
363     return ERROR_SUCCESS;
364 }
365
366 UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb, 
367                     LPCSTR table, MSIHANDLE* rec)
368 {
369     FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec);
370     return ERROR_CALL_NOT_IMPLEMENTED;
371 }
372
373 UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb,
374                     LPCWSTR table, MSIHANDLE* rec)
375 {
376     FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec);
377     return ERROR_CALL_NOT_IMPLEMENTED;
378 }