Spelling/Grammar fixes.
[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     LPWSTR szwQuery;
101
102     TRACE("%ld %s %p\n", hdb, debugstr_a(szQuery), phView);
103
104     if( szQuery )
105     {
106         UINT len = MultiByteToWideChar( CP_ACP, 0, szQuery, -1, NULL, 0 );
107         szwQuery = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
108         if( !szwQuery )
109             return ERROR_FUNCTION_FAILED;
110         MultiByteToWideChar( CP_ACP, 0, szQuery, -1, szwQuery, len );
111     }
112     else
113         szwQuery = NULL;
114
115     r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
116
117     return r;
118 }
119
120 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
121               LPCWSTR szQuery, MSIHANDLE *phView)
122 {
123     MSIDATABASE *db;
124     MSIHANDLE handle;
125     MSIQUERY *query;
126     UINT r;
127
128     TRACE("%s %p\n", debugstr_w(szQuery), phView);
129
130     if( !szQuery)
131         return ERROR_INVALID_PARAMETER;
132
133     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
134     if( !db )
135         return ERROR_INVALID_HANDLE;
136
137     /* pre allocate a handle to hold a pointer to the view */
138     handle = alloc_msihandle( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY), MSI_CloseView );
139     if( !handle )
140         return ERROR_FUNCTION_FAILED;
141     query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
142     if( !query )
143         return ERROR_FUNCTION_FAILED;
144
145     query->row = 0;
146     query->db = db;
147     query->view = NULL;
148
149     r = MSI_ParseSQL( db, szQuery, &query->view );
150     if( r != ERROR_SUCCESS )
151     {
152         MsiCloseHandle( handle );
153         return r;
154     }
155
156     *phView = handle;
157
158     return ERROR_SUCCESS;
159 }
160
161 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
162 {
163     MSIQUERY *query;
164     MSIVIEW *view;
165     MSIHANDLE handle;
166     UINT row_count = 0, col_count = 0, i, ival, ret, type;
167
168     TRACE("%ld %p\n", hView, record);
169
170     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
171     if( !query )
172         return ERROR_INVALID_HANDLE;
173     view = query->view;
174     if( !view )
175         return ERROR_FUNCTION_FAILED;
176
177     ret = view->ops->get_dimensions( view, &row_count, &col_count );
178     if( ret )
179         return ret;
180     if( !col_count )
181         return ERROR_INVALID_PARAMETER;
182
183     if( query->row >= row_count )
184         return ERROR_NO_MORE_ITEMS;
185
186     handle = MsiCreateRecord( col_count );
187     if( !handle )
188         return ERROR_FUNCTION_FAILED;
189
190     for( i=1; i<=col_count; i++ )
191     {
192         ret = view->ops->get_column_info( view, i, NULL, &type );
193         if( ret )
194         {
195             ERR("Error getting column type for %d\n", i );
196             continue;
197         }
198         ret = view->ops->fetch_int( view, query->row, i, &ival );
199         if( ret )
200         {
201             ERR("Error fetching data for %d\n", i );
202             continue;
203         }
204         if( ! (type & MSITYPE_VALID ) )
205             ERR("Invalid type!\n");
206
207         /* check if it's nul (0) - if so, don't set anything */
208         if( !ival )
209             continue;
210
211         if( type & MSITYPE_STRING )
212         {
213             LPWSTR sval = MSI_makestring( query->db, ival );
214             MsiRecordSetStringW( handle, i, sval );
215             HeapFree( GetProcessHeap(), 0, sval );
216         }
217         else
218         {
219             if( (type & MSI_DATASIZEMASK) == 2 )
220                 MsiRecordSetInteger( handle, i, ival - (1<<15) );
221             else
222                 MsiRecordSetInteger( handle, i, ival - (1<<31) );
223         }
224     }
225     query->row ++;
226
227     *record = handle;
228
229     return ERROR_SUCCESS;
230 }
231
232 UINT WINAPI MsiViewClose(MSIHANDLE hView)
233 {
234     MSIQUERY *query;
235     MSIVIEW *view;
236
237     TRACE("%ld\n", hView );
238
239     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
240     if( !query )
241         return ERROR_INVALID_HANDLE;
242
243     view = query->view;
244     if( !view )
245         return ERROR_FUNCTION_FAILED;
246     if( !view->ops->close )
247         return ERROR_FUNCTION_FAILED;
248
249     return view->ops->close( view );
250 }
251
252 UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
253 {
254     MSIQUERY *query;
255     MSIVIEW *view;
256
257     TRACE("%ld %ld\n", hView, hRec);
258
259     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
260     if( !query )
261         return ERROR_INVALID_HANDLE;
262
263     view = query->view;
264     if( !view )
265         return ERROR_FUNCTION_FAILED;
266     if( !view->ops->execute )
267         return ERROR_FUNCTION_FAILED;
268     query->row = 0;
269
270     return view->ops->execute( view, hRec );
271 }
272
273 UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
274 {
275     MSIVIEW *view;
276     MSIQUERY *query;
277     MSIHANDLE handle;
278     UINT ret, i, count = 0, type;
279     LPWSTR name;
280
281     TRACE("%ld %d %p\n", hView, info, hRec);
282
283     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
284     if( !query )
285         return ERROR_INVALID_HANDLE;
286
287     view = query->view;
288     if( !view )
289         return ERROR_FUNCTION_FAILED;
290
291     if( !view->ops->get_dimensions )
292         return ERROR_FUNCTION_FAILED;
293
294     ret = view->ops->get_dimensions( view, NULL, &count );
295     if( ret )
296         return ret;
297     if( !count )
298         return ERROR_INVALID_PARAMETER;
299
300     handle = MsiCreateRecord( count );
301     if( !handle )
302         return ERROR_FUNCTION_FAILED;
303
304     for( i=0; i<count; i++ )
305     {
306         name = NULL;
307         ret = view->ops->get_column_info( view, i+1, &name, &type );
308         if( ret != ERROR_SUCCESS )
309             continue;
310         MsiRecordSetStringW( handle, i+1, name );
311         HeapFree( GetProcessHeap(), 0, name );
312     }
313
314     *hRec = handle;
315
316     return ERROR_SUCCESS;
317 }
318
319
320 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
321 {
322     FIXME("%ld %s\n", hInstall, debugstr_a(szAction) );
323     return ERROR_CALL_NOT_IMPLEMENTED;
324 }
325
326 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
327 {
328     FIXME("%ld %s\n", hInstall, debugstr_w(szAction) );
329     return ERROR_CALL_NOT_IMPLEMENTED;
330 }
331
332 UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb, 
333                  LPCSTR szTransformFile, int iErrorCond)
334 {
335     FIXME("%ld %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
336     return ERROR_CALL_NOT_IMPLEMENTED;
337 }
338
339 UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb, 
340                  LPCWSTR szTransformFile, int iErrorCond)
341 {
342     FIXME("%ld %s %d\n", hdb, debugstr_w(szTransformFile), iErrorCond);
343     return ERROR_CALL_NOT_IMPLEMENTED;
344 }
345
346 UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
347                  LPCSTR szTransformFile, int iReserved1, int iReserved2 )
348 {
349     FIXME("%ld %ld %s %d %d\n", hdb, hdbref, 
350            debugstr_a(szTransformFile), iReserved1, iReserved2);
351     return ERROR_CALL_NOT_IMPLEMENTED;
352 }
353
354 UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
355                  LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
356 {
357     FIXME("%ld %ld %s %d %d\n", hdb, hdbref, 
358            debugstr_w(szTransformFile), iReserved1, iReserved2);
359     return ERROR_CALL_NOT_IMPLEMENTED;
360 }
361
362 UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
363 {
364     FIXME("%ld\n", hdb);
365     return ERROR_SUCCESS;
366 }
367
368 UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb, 
369                     LPCSTR table, MSIHANDLE* rec)
370 {
371     FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec);
372     return ERROR_CALL_NOT_IMPLEMENTED;
373 }
374
375 UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb,
376                     LPCWSTR table, MSIHANDLE* rec)
377 {
378     FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec);
379     return ERROR_CALL_NOT_IMPLEMENTED;
380 }
381
382 UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
383                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
384 {
385     FIXME("%ld %s %p %p\n", hInstall, debugstr_a(szFeature), piInstalled, piAction);
386     return ERROR_CALL_NOT_IMPLEMENTED;
387 }
388
389 UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPWSTR szFeature,
390                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
391 {
392     FIXME("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
393     return ERROR_CALL_NOT_IMPLEMENTED;
394 }
395
396 UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPSTR szFeature,
397                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
398 {
399     FIXME("%ld %s %p %p\n", hInstall, debugstr_a(szFeature), piInstalled, piAction);
400     return ERROR_CALL_NOT_IMPLEMENTED;
401 }
402
403 UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPWSTR szFeature,
404                   INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
405 {
406     FIXME("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
407     return ERROR_CALL_NOT_IMPLEMENTED;
408 }
409