Localization of devenum to Portuguese and minor corrections.
[wine] / dlls / msi / msiquery.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002-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., 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 "wine/unicode.h"
28 #include "msi.h"
29 #include "msiquery.h"
30 #include "objbase.h"
31 #include "objidl.h"
32 #include "msipriv.h"
33 #include "winnls.h"
34
35 #include "query.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(msi);
38
39 #if 0
40 typedef struct tagMSIQUERY
41 {
42     MSIOBJECTHDR hdr;
43     MSIVIEW *view;
44     UINT row;
45     MSIDATABASE *db;
46 } MSIQUERY;
47 #endif
48
49 UINT WINAPI MsiDatabaseIsTablePersistentA(
50               MSIHANDLE hDatabase, LPSTR szTableName)
51 {
52     FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName));
53     return ERROR_CALL_NOT_IMPLEMENTED;
54 }
55
56 UINT WINAPI MsiDatabaseIsTablePersistentW(
57               MSIHANDLE hDatabase, LPWSTR szTableName)
58 {
59     FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName));
60     return ERROR_CALL_NOT_IMPLEMENTED;
61 }
62
63 void MSI_CloseView( MSIOBJECTHDR *arg )
64 {
65     MSIQUERY *query = (MSIQUERY*) arg;
66
67     if( query->view && query->view->ops->delete )
68         query->view->ops->delete( query->view );
69     msiobj_release( &query->db->hdr );
70 }
71
72 UINT VIEW_find_column( MSIVIEW *table, LPWSTR name, UINT *n )
73 {
74     LPWSTR col_name;
75     UINT i, count, r;
76
77     r = table->ops->get_dimensions( table, NULL, &count );
78     if( r != ERROR_SUCCESS )
79         return r;
80
81     for( i=1; i<=count; i++ )
82     {
83         INT x;
84
85         col_name = NULL;
86         r = table->ops->get_column_info( table, i, &col_name, NULL );
87         if( r != ERROR_SUCCESS )
88             return r;
89         x = lstrcmpW( name, col_name );
90         HeapFree( GetProcessHeap(), 0, col_name );
91         if( !x )
92         {
93             *n = i;
94             return ERROR_SUCCESS;
95         }
96     }
97
98     return ERROR_INVALID_PARAMETER;
99 }
100
101 UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
102               LPCSTR szQuery, MSIHANDLE *phView)
103 {
104     UINT r;
105     LPWSTR szwQuery;
106
107     TRACE("%ld %s %p\n", hdb, debugstr_a(szQuery), phView);
108
109     if( szQuery )
110     {
111         UINT len = MultiByteToWideChar( CP_ACP, 0, szQuery, -1, NULL, 0 );
112         szwQuery = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
113         if( !szwQuery )
114             return ERROR_FUNCTION_FAILED;
115         MultiByteToWideChar( CP_ACP, 0, szQuery, -1, szwQuery, len );
116     }
117     else
118         szwQuery = NULL;
119
120     r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
121
122     return r;
123 }
124
125 UINT MSI_DatabaseOpenViewW(MSIDATABASE *db,
126               LPCWSTR szQuery, MSIQUERY **pView)
127 {
128     MSIQUERY *query;
129     UINT r;
130
131     TRACE("%s %p\n", debugstr_w(szQuery), pView);
132
133     if( !szQuery)
134         return ERROR_INVALID_PARAMETER;
135
136     /* pre allocate a handle to hold a pointer to the view */
137     query = alloc_msiobject( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY),
138                               MSI_CloseView );
139     if( !query )
140         return ERROR_FUNCTION_FAILED;
141
142     msiobj_addref( &db->hdr );
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         msiobj_addref( &query->hdr );
151         *pView = query;
152     }
153
154     msiobj_release( &query->hdr );
155     return r;
156 }
157
158 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
159               LPCWSTR szQuery, MSIHANDLE *phView)
160 {
161     MSIDATABASE *db;
162     MSIQUERY *query = NULL;
163     UINT ret;
164
165     TRACE("%s %p\n", debugstr_w(szQuery), phView);
166
167     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
168     if( !db )
169         return ERROR_INVALID_HANDLE;
170
171     ret = MSI_DatabaseOpenViewW( db, szQuery, &query );
172     if( ret == ERROR_SUCCESS )
173     {
174         *phView = alloc_msihandle( &query->hdr );
175         msiobj_release( &query->hdr );
176     }
177     msiobj_release( &db->hdr );
178
179     return ret;
180 }
181
182 UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
183 {
184     MSIVIEW *view;
185     MSIRECORD *rec;
186     UINT row_count = 0, col_count = 0, i, ival, ret, type;
187
188     TRACE("%p %p\n", query, prec );
189
190     view = query->view;
191     if( !view )
192         return ERROR_FUNCTION_FAILED;
193
194     ret = view->ops->get_dimensions( view, &row_count, &col_count );
195     if( ret )
196         return ret;
197     if( !col_count )
198         return ERROR_INVALID_PARAMETER;
199
200     if( query->row >= row_count )
201         return ERROR_NO_MORE_ITEMS;
202
203     rec = MSI_CreateRecord( col_count );
204     if( !rec )
205         return ERROR_FUNCTION_FAILED;
206
207     for( i=1; i<=col_count; i++ )
208     {
209         ret = view->ops->get_column_info( view, i, NULL, &type );
210         if( ret )
211         {
212             ERR("Error getting column type for %d\n", i );
213             continue;
214         }
215         if (( type != MSITYPE_BINARY) && (type != (MSITYPE_BINARY |
216                                                    MSITYPE_NULLABLE)))
217         {
218             ret = view->ops->fetch_int( view, query->row, i, &ival );
219             if( ret )
220             {
221                 ERR("Error fetching data for %d\n", i );
222                 continue;
223             }
224             if( ! (type & MSITYPE_VALID ) )
225                 ERR("Invalid type!\n");
226
227             /* check if it's nul (0) - if so, don't set anything */
228             if( !ival )
229                 continue;
230
231             if( type & MSITYPE_STRING )
232             {
233                 LPWSTR sval;
234
235                 sval = MSI_makestring( query->db, ival );
236                 MSI_RecordSetStringW( rec, i, sval );
237                 HeapFree( GetProcessHeap(), 0, sval );
238             }
239             else
240             {
241                 if( (type & MSI_DATASIZEMASK) == 2 )
242                     MSI_RecordSetInteger( rec, i, ival - (1<<15) );
243                 else
244                     MSI_RecordSetInteger( rec, i, ival - (1<<31) );
245             }
246         }
247         else
248         {
249             IStream *stm = NULL;
250
251             ret = view->ops->fetch_stream( view, query->row, i, &stm );
252             if( ( ret == ERROR_SUCCESS ) && stm )
253             {
254                 MSI_RecordSetIStream( rec, i, stm );
255                 IStream_Release( stm );
256             }
257             else
258                 ERR("failed to get stream\n");
259         }
260     }
261     query->row ++;
262
263     *prec = rec;
264
265     return ERROR_SUCCESS;
266 }
267
268 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
269 {
270     MSIQUERY *query;
271     MSIRECORD *rec = NULL;
272     UINT ret;
273
274     TRACE("%ld %p\n", hView, record);
275
276     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
277     if( !query )
278         return ERROR_INVALID_HANDLE;
279     ret = MSI_ViewFetch( query, &rec );
280     if( ret == ERROR_SUCCESS )
281     {
282         *record = alloc_msihandle( &rec->hdr );
283         msiobj_release( &rec->hdr );
284     }
285     msiobj_release( &query->hdr );
286     return ret;
287 }
288
289 UINT MSI_ViewClose(MSIQUERY *query)
290 {
291     MSIVIEW *view;
292
293     TRACE("%p\n", query );
294
295     view = query->view;
296     if( !view )
297         return ERROR_FUNCTION_FAILED;
298     if( !view->ops->close )
299         return ERROR_FUNCTION_FAILED;
300
301     return view->ops->close( view );
302 }
303
304 UINT WINAPI MsiViewClose(MSIHANDLE hView)
305 {
306     MSIQUERY *query;
307     UINT ret;
308
309     TRACE("%ld\n", hView );
310
311     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
312     if( !query )
313         return ERROR_INVALID_HANDLE;
314
315     ret = MSI_ViewClose( query );
316     msiobj_release( &query->hdr );
317     return ret;
318 }
319
320 UINT MSI_ViewExecute(MSIQUERY *query, MSIRECORD *rec )
321 {
322     MSIVIEW *view;
323
324     TRACE("%p %p\n", query, rec);
325
326     view = query->view;
327     if( !view )
328         return ERROR_FUNCTION_FAILED;
329     if( !view->ops->execute )
330         return ERROR_FUNCTION_FAILED;
331     query->row = 0;
332
333     return view->ops->execute( view, rec );
334 }
335
336 UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
337 {
338     MSIQUERY *query;
339     MSIRECORD *rec = NULL;
340     UINT ret;
341     
342     TRACE("%ld %ld\n", hView, hRec);
343
344     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
345     if( !query )
346         return ERROR_INVALID_HANDLE;
347
348     if( hRec )
349     {
350         rec = msihandle2msiinfo( hRec, MSIHANDLETYPE_RECORD );
351         if( !rec )
352         {
353             ret = ERROR_INVALID_HANDLE;
354             goto out;
355         }
356     }
357
358     ret = MSI_ViewExecute( query, rec );
359 out:
360     if( query )
361         msiobj_release( &query->hdr );
362     if( rec )
363         msiobj_release( &rec->hdr );
364
365     return ret;
366 }
367
368 UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
369 {
370     MSIVIEW *view;
371     MSIQUERY *query;
372     MSIHANDLE handle;
373     UINT ret, i, count = 0, type;
374     LPWSTR name;
375
376     TRACE("%ld %d %p\n", hView, info, hRec);
377
378     query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
379     if( !query )
380         return ERROR_INVALID_HANDLE;
381
382     view = query->view;
383     if( !view )
384         return ERROR_FUNCTION_FAILED;
385
386     if( !view->ops->get_dimensions )
387         return ERROR_FUNCTION_FAILED;
388
389     ret = view->ops->get_dimensions( view, NULL, &count );
390     if( ret )
391         return ret;
392     if( !count )
393         return ERROR_INVALID_PARAMETER;
394
395     handle = MsiCreateRecord( count );
396     if( !handle )
397         return ERROR_FUNCTION_FAILED;
398
399     for( i=0; i<count; i++ )
400     {
401         name = NULL;
402         ret = view->ops->get_column_info( view, i+1, &name, &type );
403         if( ret != ERROR_SUCCESS )
404             continue;
405         MsiRecordSetStringW( handle, i+1, name );
406         HeapFree( GetProcessHeap(), 0, name );
407     }
408
409     *hRec = handle;
410
411     return ERROR_SUCCESS;
412 }
413
414 UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb, 
415                  LPCSTR szTransformFile, int iErrorCond)
416 {
417     FIXME("%ld %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
418     return ERROR_CALL_NOT_IMPLEMENTED;
419 }
420
421 UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb, 
422                  LPCWSTR szTransformFile, int iErrorCond)
423 {
424     FIXME("%ld %s %d\n", hdb, debugstr_w(szTransformFile), iErrorCond);
425     return ERROR_CALL_NOT_IMPLEMENTED;
426 }
427
428 UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
429                  LPCSTR szTransformFile, int iReserved1, int iReserved2 )
430 {
431     FIXME("%ld %ld %s %d %d\n", hdb, hdbref, 
432            debugstr_a(szTransformFile), iReserved1, iReserved2);
433     return ERROR_CALL_NOT_IMPLEMENTED;
434 }
435
436 UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
437                  LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
438 {
439     FIXME("%ld %ld %s %d %d\n", hdb, hdbref, 
440            debugstr_w(szTransformFile), iReserved1, iReserved2);
441     return ERROR_CALL_NOT_IMPLEMENTED;
442 }
443
444 UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
445 {
446     MSIDATABASE *db;
447     UINT r;
448
449     TRACE("%ld\n", hdb);
450
451     db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
452     if( !db )
453         return ERROR_INVALID_HANDLE;
454
455     /* FIXME: lock the database */
456
457     r = MSI_CommitTables( db );
458
459     /* FIXME: unlock the database */
460
461     return r;
462 }
463
464 UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb, 
465                     LPCSTR table, MSIHANDLE* rec)
466 {
467     FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec);
468     return ERROR_CALL_NOT_IMPLEMENTED;
469 }
470
471 UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb,
472                     LPCWSTR table, MSIHANDLE* rec)
473 {
474     FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec);
475     return ERROR_CALL_NOT_IMPLEMENTED;
476 }
477
478 UINT WINAPI MsiViewModify(MSIHANDLE hView, MSIMODIFY eModifyMode, MSIHANDLE
479 hRecord)
480 {
481     FIXME("%ld %x %ld\n",hView, eModifyMode, hRecord);
482     return ERROR_CALL_NOT_IMPLEMENTED;
483 }