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
28 #include "wine/debug.h"
29 #include "wine/unicode.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msi);
41 void MSI_CloseView( MSIOBJECTHDR *arg )
43 MSIQUERY *query = (MSIQUERY*) arg;
45 if( query->view && query->view->ops->delete )
46 query->view->ops->delete( query->view );
47 msiobj_release( &query->db->hdr );
50 UINT VIEW_find_column( MSIVIEW *table, LPWSTR name, UINT *n )
55 r = table->ops->get_dimensions( table, NULL, &count );
56 if( r != ERROR_SUCCESS )
59 for( i=1; i<=count; i++ )
64 r = table->ops->get_column_info( table, i, &col_name, NULL );
65 if( r != ERROR_SUCCESS )
67 x = lstrcmpW( name, col_name );
68 HeapFree( GetProcessHeap(), 0, col_name );
76 return ERROR_INVALID_PARAMETER;
79 UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
80 LPCSTR szQuery, MSIHANDLE *phView)
85 TRACE("%ld %s %p\n", hdb, debugstr_a(szQuery), phView);
89 UINT len = MultiByteToWideChar( CP_ACP, 0, szQuery, -1, NULL, 0 );
90 szwQuery = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
92 return ERROR_FUNCTION_FAILED;
93 MultiByteToWideChar( CP_ACP, 0, szQuery, -1, szwQuery, len );
98 r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
100 HeapFree( GetProcessHeap(), 0, szwQuery );
104 UINT MSI_DatabaseOpenViewW(MSIDATABASE *db,
105 LPCWSTR szQuery, MSIQUERY **pView)
110 TRACE("%s %p\n", debugstr_w(szQuery), pView);
113 return ERROR_INVALID_PARAMETER;
115 /* pre allocate a handle to hold a pointer to the view */
116 query = alloc_msiobject( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY),
119 return ERROR_FUNCTION_FAILED;
121 msiobj_addref( &db->hdr );
126 r = MSI_ParseSQL( db, szQuery, &query->view );
127 if( r == ERROR_SUCCESS )
129 msiobj_addref( &query->hdr );
133 msiobj_release( &query->hdr );
137 UINT MSI_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... )
144 /* figure out how much space we need to allocate */
146 sz = strlenW(fmt) + 1;
156 case 's': /* a string */
157 sz += strlenW(va_arg(va,LPCWSTR));
160 case 'i': /* an integer -2147483648 seems to be longest */
162 (void)va_arg(va,int);
164 case '%': /* a single % - leave it alone */
167 FIXME("Unhandled character type %c\n",*p);
173 /* construct the string */
174 szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR));
176 vsnprintfW(szQuery, sz, fmt, va);
179 /* perform the query */
180 rc = MSI_DatabaseOpenViewW(db, szQuery, view);
181 HeapFree(GetProcessHeap(), 0, szQuery);
185 UINT MSI_IterateRecords( MSIQUERY *view, DWORD *count,
186 record_func func, LPVOID param )
188 MSIRECORD *rec = NULL;
189 UINT r, n = 0, max = 0;
191 r = MSI_ViewExecute( view, NULL );
192 if( r != ERROR_SUCCESS )
198 /* iterate a query */
199 for( n = 0; (max == 0) || (n < max); n++ )
201 r = MSI_ViewFetch( view, &rec );
202 if( r != ERROR_SUCCESS )
204 r = func( rec, param );
205 msiobj_release( &rec->hdr );
206 if( r != ERROR_SUCCESS )
210 MSI_ViewClose( view );
218 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
219 LPCWSTR szQuery, MSIHANDLE *phView)
222 MSIQUERY *query = NULL;
225 TRACE("%s %p\n", debugstr_w(szQuery), phView);
227 db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
229 return ERROR_INVALID_HANDLE;
231 ret = MSI_DatabaseOpenViewW( db, szQuery, &query );
232 if( ret == ERROR_SUCCESS )
234 *phView = alloc_msihandle( &query->hdr );
235 msiobj_release( &query->hdr );
237 msiobj_release( &db->hdr );
242 UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
246 UINT row_count = 0, col_count = 0, i, ival, ret, type;
248 TRACE("%p %p\n", query, prec );
252 return ERROR_FUNCTION_FAILED;
254 ret = view->ops->get_dimensions( view, &row_count, &col_count );
258 return ERROR_INVALID_PARAMETER;
260 if( query->row >= row_count )
261 return ERROR_NO_MORE_ITEMS;
263 rec = MSI_CreateRecord( col_count );
265 return ERROR_FUNCTION_FAILED;
267 for( i=1; i<=col_count; i++ )
269 ret = view->ops->get_column_info( view, i, NULL, &type );
272 ERR("Error getting column type for %d\n", i );
275 if (( type != MSITYPE_BINARY) && (type != (MSITYPE_BINARY |
278 ret = view->ops->fetch_int( view, query->row, i, &ival );
281 ERR("Error fetching data for %d\n", i );
284 if( ! (type & MSITYPE_VALID ) )
285 ERR("Invalid type!\n");
287 /* check if it's nul (0) - if so, don't set anything */
291 if( type & MSITYPE_STRING )
295 sval = MSI_makestring( query->db, ival );
296 MSI_RecordSetStringW( rec, i, sval );
297 HeapFree( GetProcessHeap(), 0, sval );
301 if( (type & MSI_DATASIZEMASK) == 2 )
302 MSI_RecordSetInteger( rec, i, ival - (1<<15) );
304 MSI_RecordSetInteger( rec, i, ival - (1<<31) );
311 ret = view->ops->fetch_stream( view, query->row, i, &stm );
312 if( ( ret == ERROR_SUCCESS ) && stm )
314 MSI_RecordSetIStream( rec, i, stm );
315 IStream_Release( stm );
318 ERR("failed to get stream\n");
325 return ERROR_SUCCESS;
328 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
331 MSIRECORD *rec = NULL;
334 TRACE("%ld %p\n", hView, record);
336 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
338 return ERROR_INVALID_HANDLE;
339 ret = MSI_ViewFetch( query, &rec );
340 if( ret == ERROR_SUCCESS )
342 *record = alloc_msihandle( &rec->hdr );
343 msiobj_release( &rec->hdr );
345 msiobj_release( &query->hdr );
349 UINT MSI_ViewClose(MSIQUERY *query)
353 TRACE("%p\n", query );
357 return ERROR_FUNCTION_FAILED;
358 if( !view->ops->close )
359 return ERROR_FUNCTION_FAILED;
361 return view->ops->close( view );
364 UINT WINAPI MsiViewClose(MSIHANDLE hView)
369 TRACE("%ld\n", hView );
371 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
373 return ERROR_INVALID_HANDLE;
375 ret = MSI_ViewClose( query );
376 msiobj_release( &query->hdr );
380 UINT MSI_ViewExecute(MSIQUERY *query, MSIRECORD *rec )
384 TRACE("%p %p\n", query, rec);
388 return ERROR_FUNCTION_FAILED;
389 if( !view->ops->execute )
390 return ERROR_FUNCTION_FAILED;
393 return view->ops->execute( view, rec );
396 UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
399 MSIRECORD *rec = NULL;
402 TRACE("%ld %ld\n", hView, hRec);
404 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
406 return ERROR_INVALID_HANDLE;
410 rec = msihandle2msiinfo( hRec, MSIHANDLETYPE_RECORD );
413 ret = ERROR_INVALID_HANDLE;
418 msiobj_lock( &rec->hdr );
419 ret = MSI_ViewExecute( query, rec );
420 msiobj_unlock( &rec->hdr );
424 msiobj_release( &query->hdr );
426 msiobj_release( &rec->hdr );
431 UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
436 UINT ret, i, count = 0, type;
439 TRACE("%ld %d %p\n", hView, info, hRec);
441 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
443 return ERROR_INVALID_HANDLE;
447 return ERROR_FUNCTION_FAILED;
449 if( !view->ops->get_dimensions )
450 return ERROR_FUNCTION_FAILED;
452 ret = view->ops->get_dimensions( view, NULL, &count );
456 return ERROR_INVALID_PARAMETER;
458 handle = MsiCreateRecord( count );
460 return ERROR_FUNCTION_FAILED;
462 for( i=0; i<count; i++ )
465 ret = view->ops->get_column_info( view, i+1, &name, &type );
466 if( ret != ERROR_SUCCESS )
468 MsiRecordSetStringW( handle, i+1, name );
469 HeapFree( GetProcessHeap(), 0, name );
474 return ERROR_SUCCESS;
477 UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb,
478 LPCSTR szTransformFile, int iErrorCond)
480 FIXME("%ld %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
481 return ERROR_CALL_NOT_IMPLEMENTED;
484 UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
485 LPCWSTR szTransformFile, int iErrorCond)
487 FIXME("%ld %s %d\n", hdb, debugstr_w(szTransformFile), iErrorCond);
488 return ERROR_CALL_NOT_IMPLEMENTED;
491 UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
492 LPCSTR szTransformFile, int iReserved1, int iReserved2 )
494 FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
495 debugstr_a(szTransformFile), iReserved1, iReserved2);
496 return ERROR_CALL_NOT_IMPLEMENTED;
499 UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
500 LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
502 FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
503 debugstr_w(szTransformFile), iReserved1, iReserved2);
504 return ERROR_CALL_NOT_IMPLEMENTED;
507 UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
514 db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
516 return ERROR_INVALID_HANDLE;
518 /* FIXME: lock the database */
520 r = MSI_CommitTables( db );
522 /* FIXME: unlock the database */
524 msiobj_release( &db->hdr );
529 UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb,
530 LPCSTR table, MSIHANDLE* rec)
532 FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec);
533 return ERROR_CALL_NOT_IMPLEMENTED;
536 UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb,
537 LPCWSTR table, MSIHANDLE* rec)
539 FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec);
540 return ERROR_CALL_NOT_IMPLEMENTED;
543 UINT WINAPI MsiViewModify(MSIHANDLE hView, MSIMODIFY eModifyMode, MSIHANDLE
546 FIXME("%ld %x %ld\n",hView, eModifyMode, hRecord);
547 return ERROR_CALL_NOT_IMPLEMENTED;
550 UINT WINAPI MsiDatabaseIsTablePersistentA(
551 MSIHANDLE hDatabase, LPSTR szTableName)
553 FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName));
554 return ERROR_CALL_NOT_IMPLEMENTED;
557 UINT WINAPI MsiDatabaseIsTablePersistentW(
558 MSIHANDLE hDatabase, LPWSTR szTableName)
560 FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName));
561 return ERROR_CALL_NOT_IMPLEMENTED;