Authors: Mike McCormack <mike@codeweavers.com>, Aric Stewart <aric@codeweavers.com>
[wine/multimedia.git] / dlls / msi / msiquery.c
blob4b82273b3077b6bfa3bf426dce2aa3356f00e719
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002-2004 Mike McCormack for CodeWeavers
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.
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.
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
21 #include <stdarg.h>
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"
35 #include "query.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msi);
39 #if 0
40 typedef struct tagMSIQUERY
42 MSIOBJECTHDR hdr;
43 MSIVIEW *view;
44 UINT row;
45 MSIDATABASE *db;
46 } MSIQUERY;
47 #endif
49 UINT WINAPI MsiDatabaseIsTablePersistentA(
50 MSIHANDLE hDatabase, LPSTR szTableName)
52 FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName));
53 return ERROR_CALL_NOT_IMPLEMENTED;
56 UINT WINAPI MsiDatabaseIsTablePersistentW(
57 MSIHANDLE hDatabase, LPWSTR szTableName)
59 FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName));
60 return ERROR_CALL_NOT_IMPLEMENTED;
63 void MSI_CloseView( MSIOBJECTHDR *arg )
65 MSIQUERY *query = (MSIQUERY*) arg;
67 if( query->view && query->view->ops->delete )
68 query->view->ops->delete( query->view );
69 msiobj_release( &query->db->hdr );
72 UINT VIEW_find_column( MSIVIEW *table, LPWSTR name, UINT *n )
74 LPWSTR col_name;
75 UINT i, count, r;
77 r = table->ops->get_dimensions( table, NULL, &count );
78 if( r != ERROR_SUCCESS )
79 return r;
81 for( i=1; i<=count; i++ )
83 INT x;
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 )
93 *n = i;
94 return ERROR_SUCCESS;
98 return ERROR_INVALID_PARAMETER;
101 UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
102 LPCSTR szQuery, MSIHANDLE *phView)
104 UINT r;
105 LPWSTR szwQuery;
107 TRACE("%ld %s %p\n", hdb, debugstr_a(szQuery), phView);
109 if( szQuery )
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 );
117 else
118 szwQuery = NULL;
120 r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
122 return r;
125 UINT MSI_DatabaseOpenViewW(MSIDATABASE *db,
126 LPCWSTR szQuery, MSIQUERY **pView)
128 MSIQUERY *query;
129 UINT r;
131 TRACE("%s %p\n", debugstr_w(szQuery), pView);
133 if( !szQuery)
134 return ERROR_INVALID_PARAMETER;
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;
142 msiobj_addref( &db->hdr );
143 query->row = 0;
144 query->db = db;
145 query->view = NULL;
147 r = MSI_ParseSQL( db, szQuery, &query->view );
148 if( r == ERROR_SUCCESS )
150 msiobj_addref( &query->hdr );
151 *pView = query;
154 msiobj_release( &query->hdr );
155 return ERROR_SUCCESS;
158 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
159 LPCWSTR szQuery, MSIHANDLE *phView)
161 MSIDATABASE *db;
162 MSIQUERY *query = NULL;
163 UINT ret;
165 TRACE("%s %p\n", debugstr_w(szQuery), phView);
167 db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
168 if( !db )
169 return ERROR_INVALID_HANDLE;
171 ret = MSI_DatabaseOpenViewW( db, szQuery, &query );
172 if( ret == ERROR_SUCCESS )
174 *phView = alloc_msihandle( &query->hdr );
175 msiobj_release( &query->hdr );
177 msiobj_release( &db->hdr );
179 return ret;
182 UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
184 MSIVIEW *view;
185 MSIRECORD *rec;
186 UINT row_count = 0, col_count = 0, i, ival, ret, type;
188 TRACE("%p %p\n", query, prec );
190 view = query->view;
191 if( !view )
192 return ERROR_FUNCTION_FAILED;
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;
200 if( query->row >= row_count )
201 return ERROR_NO_MORE_ITEMS;
203 rec = MSI_CreateRecord( col_count );
204 if( !rec )
205 return ERROR_FUNCTION_FAILED;
207 for( i=1; i<=col_count; i++ )
209 ret = view->ops->get_column_info( view, i, NULL, &type );
210 if( ret )
212 ERR("Error getting column type for %d\n", i );
213 continue;
215 if (( type != MSITYPE_BINARY) && (type != (MSITYPE_BINARY |
216 MSITYPE_NULLABLE)))
218 ret = view->ops->fetch_int( view, query->row, i, &ival );
219 if( ret )
221 ERR("Error fetching data for %d\n", i );
222 continue;
224 if( ! (type & MSITYPE_VALID ) )
225 ERR("Invalid type!\n");
227 /* check if it's nul (0) - if so, don't set anything */
228 if( !ival )
229 continue;
231 if( type & MSITYPE_STRING )
233 LPWSTR sval;
235 sval = MSI_makestring( query->db, ival );
236 MSI_RecordSetStringW( rec, i, sval );
237 HeapFree( GetProcessHeap(), 0, sval );
239 else
241 if( (type & MSI_DATASIZEMASK) == 2 )
242 MSI_RecordSetInteger( rec, i, ival - (1<<15) );
243 else
244 MSI_RecordSetInteger( rec, i, ival - (1<<31) );
247 else
249 IStream *stm = NULL;
251 ret = view->ops->fetch_stream( view, query->row, i, &stm );
252 if( ( ret == ERROR_SUCCESS ) && stm )
254 MSI_RecordSetIStream( rec, i, stm );
255 IStream_Release( stm );
257 else
258 ERR("failed to get stream\n");
261 query->row ++;
263 *prec = rec;
265 return ERROR_SUCCESS;
268 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
270 MSIQUERY *query;
271 MSIRECORD *rec = NULL;
272 UINT ret;
274 TRACE("%ld %p\n", hView, record);
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 )
282 *record = alloc_msihandle( &rec->hdr );
283 msiobj_release( &rec->hdr );
285 msiobj_release( &query->hdr );
286 return ret;
289 UINT MSI_ViewClose(MSIQUERY *query)
291 MSIVIEW *view;
293 TRACE("%p\n", query );
295 view = query->view;
296 if( !view )
297 return ERROR_FUNCTION_FAILED;
298 if( !view->ops->close )
299 return ERROR_FUNCTION_FAILED;
301 return view->ops->close( view );
304 UINT WINAPI MsiViewClose(MSIHANDLE hView)
306 MSIQUERY *query;
307 UINT ret;
309 TRACE("%ld\n", hView );
311 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
312 if( !query )
313 return ERROR_INVALID_HANDLE;
315 ret = MSI_ViewClose( query );
316 msiobj_release( &query->hdr );
317 return ret;
320 UINT MSI_ViewExecute(MSIQUERY *query, MSIRECORD *rec )
322 MSIVIEW *view;
324 TRACE("%p %p\n", query, rec);
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;
333 return view->ops->execute( view, rec );
336 UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
338 MSIQUERY *query;
339 MSIRECORD *rec = NULL;
340 UINT ret;
342 TRACE("%ld %ld\n", hView, hRec);
344 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
345 if( !query )
346 return ERROR_INVALID_HANDLE;
348 if( hRec )
350 rec = msihandle2msiinfo( hRec, MSIHANDLETYPE_RECORD );
351 if( !rec )
353 ret = ERROR_INVALID_HANDLE;
354 goto out;
358 ret = MSI_ViewExecute( query, rec );
359 out:
360 if( query )
361 msiobj_release( &query->hdr );
362 if( rec )
363 msiobj_release( &rec->hdr );
365 return ret;
368 UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
370 MSIVIEW *view;
371 MSIQUERY *query;
372 MSIHANDLE handle;
373 UINT ret, i, count = 0, type;
374 LPWSTR name;
376 TRACE("%ld %d %p\n", hView, info, hRec);
378 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
379 if( !query )
380 return ERROR_INVALID_HANDLE;
382 view = query->view;
383 if( !view )
384 return ERROR_FUNCTION_FAILED;
386 if( !view->ops->get_dimensions )
387 return ERROR_FUNCTION_FAILED;
389 ret = view->ops->get_dimensions( view, NULL, &count );
390 if( ret )
391 return ret;
392 if( !count )
393 return ERROR_INVALID_PARAMETER;
395 handle = MsiCreateRecord( count );
396 if( !handle )
397 return ERROR_FUNCTION_FAILED;
399 for( i=0; i<count; i++ )
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 );
409 *hRec = handle;
411 return ERROR_SUCCESS;
414 UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb,
415 LPCSTR szTransformFile, int iErrorCond)
417 FIXME("%ld %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
418 return ERROR_CALL_NOT_IMPLEMENTED;
421 UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
422 LPCWSTR szTransformFile, int iErrorCond)
424 FIXME("%ld %s %d\n", hdb, debugstr_w(szTransformFile), iErrorCond);
425 return ERROR_CALL_NOT_IMPLEMENTED;
428 UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
429 LPCSTR szTransformFile, int iReserved1, int iReserved2 )
431 FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
432 debugstr_a(szTransformFile), iReserved1, iReserved2);
433 return ERROR_CALL_NOT_IMPLEMENTED;
436 UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
437 LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
439 FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
440 debugstr_w(szTransformFile), iReserved1, iReserved2);
441 return ERROR_CALL_NOT_IMPLEMENTED;
444 UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
446 MSIDATABASE *db;
447 UINT r;
449 TRACE("%ld\n", hdb);
451 db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
452 if( !db )
453 return ERROR_INVALID_HANDLE;
455 /* FIXME: lock the database */
457 r = MSI_CommitTables( db );
459 /* FIXME: unlock the database */
461 return r;
464 UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb,
465 LPCSTR table, MSIHANDLE* rec)
467 FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec);
468 return ERROR_CALL_NOT_IMPLEMENTED;
471 UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb,
472 LPCWSTR table, MSIHANDLE* rec)
474 FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec);
475 return ERROR_CALL_NOT_IMPLEMENTED;
478 UINT WINAPI MsiViewModify(MSIHANDLE hView, MSIMODIFY eModifyMode, MSIHANDLE
479 hRecord)
481 FIXME("%ld %x %ld\n",hView, eModifyMode, hRecord);
482 return ERROR_CALL_NOT_IMPLEMENTED;