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 WINAPI
MsiDatabaseOpenViewW(MSIHANDLE hdb
,
186 LPCWSTR szQuery
, MSIHANDLE
*phView
)
189 MSIQUERY
*query
= NULL
;
192 TRACE("%s %p\n", debugstr_w(szQuery
), phView
);
194 db
= msihandle2msiinfo( hdb
, MSIHANDLETYPE_DATABASE
);
196 return ERROR_INVALID_HANDLE
;
198 ret
= MSI_DatabaseOpenViewW( db
, szQuery
, &query
);
199 if( ret
== ERROR_SUCCESS
)
201 *phView
= alloc_msihandle( &query
->hdr
);
202 msiobj_release( &query
->hdr
);
204 msiobj_release( &db
->hdr
);
209 UINT
MSI_ViewFetch(MSIQUERY
*query
, MSIRECORD
**prec
)
213 UINT row_count
= 0, col_count
= 0, i
, ival
, ret
, type
;
215 TRACE("%p %p\n", query
, prec
);
219 return ERROR_FUNCTION_FAILED
;
221 ret
= view
->ops
->get_dimensions( view
, &row_count
, &col_count
);
225 return ERROR_INVALID_PARAMETER
;
227 if( query
->row
>= row_count
)
228 return ERROR_NO_MORE_ITEMS
;
230 rec
= MSI_CreateRecord( col_count
);
232 return ERROR_FUNCTION_FAILED
;
234 for( i
=1; i
<=col_count
; i
++ )
236 ret
= view
->ops
->get_column_info( view
, i
, NULL
, &type
);
239 ERR("Error getting column type for %d\n", i
);
242 if (( type
!= MSITYPE_BINARY
) && (type
!= (MSITYPE_BINARY
|
245 ret
= view
->ops
->fetch_int( view
, query
->row
, i
, &ival
);
248 ERR("Error fetching data for %d\n", i
);
251 if( ! (type
& MSITYPE_VALID
) )
252 ERR("Invalid type!\n");
254 /* check if it's nul (0) - if so, don't set anything */
258 if( type
& MSITYPE_STRING
)
262 sval
= MSI_makestring( query
->db
, ival
);
263 MSI_RecordSetStringW( rec
, i
, sval
);
264 HeapFree( GetProcessHeap(), 0, sval
);
268 if( (type
& MSI_DATASIZEMASK
) == 2 )
269 MSI_RecordSetInteger( rec
, i
, ival
- (1<<15) );
271 MSI_RecordSetInteger( rec
, i
, ival
- (1<<31) );
278 ret
= view
->ops
->fetch_stream( view
, query
->row
, i
, &stm
);
279 if( ( ret
== ERROR_SUCCESS
) && stm
)
281 MSI_RecordSetIStream( rec
, i
, stm
);
282 IStream_Release( stm
);
285 ERR("failed to get stream\n");
292 return ERROR_SUCCESS
;
295 UINT WINAPI
MsiViewFetch(MSIHANDLE hView
, MSIHANDLE
*record
)
298 MSIRECORD
*rec
= NULL
;
301 TRACE("%ld %p\n", hView
, record
);
303 query
= msihandle2msiinfo( hView
, MSIHANDLETYPE_VIEW
);
305 return ERROR_INVALID_HANDLE
;
306 ret
= MSI_ViewFetch( query
, &rec
);
307 if( ret
== ERROR_SUCCESS
)
309 *record
= alloc_msihandle( &rec
->hdr
);
310 msiobj_release( &rec
->hdr
);
312 msiobj_release( &query
->hdr
);
316 UINT
MSI_ViewClose(MSIQUERY
*query
)
320 TRACE("%p\n", query
);
324 return ERROR_FUNCTION_FAILED
;
325 if( !view
->ops
->close
)
326 return ERROR_FUNCTION_FAILED
;
328 return view
->ops
->close( view
);
331 UINT WINAPI
MsiViewClose(MSIHANDLE hView
)
336 TRACE("%ld\n", hView
);
338 query
= msihandle2msiinfo( hView
, MSIHANDLETYPE_VIEW
);
340 return ERROR_INVALID_HANDLE
;
342 ret
= MSI_ViewClose( query
);
343 msiobj_release( &query
->hdr
);
347 UINT
MSI_ViewExecute(MSIQUERY
*query
, MSIRECORD
*rec
)
351 TRACE("%p %p\n", query
, rec
);
355 return ERROR_FUNCTION_FAILED
;
356 if( !view
->ops
->execute
)
357 return ERROR_FUNCTION_FAILED
;
360 return view
->ops
->execute( view
, rec
);
363 UINT WINAPI
MsiViewExecute(MSIHANDLE hView
, MSIHANDLE hRec
)
366 MSIRECORD
*rec
= NULL
;
369 TRACE("%ld %ld\n", hView
, hRec
);
371 query
= msihandle2msiinfo( hView
, MSIHANDLETYPE_VIEW
);
373 return ERROR_INVALID_HANDLE
;
377 rec
= msihandle2msiinfo( hRec
, MSIHANDLETYPE_RECORD
);
380 ret
= ERROR_INVALID_HANDLE
;
385 msiobj_lock( &rec
->hdr
);
386 ret
= MSI_ViewExecute( query
, rec
);
387 msiobj_unlock( &rec
->hdr
);
391 msiobj_release( &query
->hdr
);
393 msiobj_release( &rec
->hdr
);
398 UINT WINAPI
MsiViewGetColumnInfo(MSIHANDLE hView
, MSICOLINFO info
, MSIHANDLE
*hRec
)
403 UINT ret
, i
, count
= 0, type
;
406 TRACE("%ld %d %p\n", hView
, info
, hRec
);
408 query
= msihandle2msiinfo( hView
, MSIHANDLETYPE_VIEW
);
410 return ERROR_INVALID_HANDLE
;
414 return ERROR_FUNCTION_FAILED
;
416 if( !view
->ops
->get_dimensions
)
417 return ERROR_FUNCTION_FAILED
;
419 ret
= view
->ops
->get_dimensions( view
, NULL
, &count
);
423 return ERROR_INVALID_PARAMETER
;
425 handle
= MsiCreateRecord( count
);
427 return ERROR_FUNCTION_FAILED
;
429 for( i
=0; i
<count
; i
++ )
432 ret
= view
->ops
->get_column_info( view
, i
+1, &name
, &type
);
433 if( ret
!= ERROR_SUCCESS
)
435 MsiRecordSetStringW( handle
, i
+1, name
);
436 HeapFree( GetProcessHeap(), 0, name
);
441 return ERROR_SUCCESS
;
444 UINT WINAPI
MsiDatabaseApplyTransformA( MSIHANDLE hdb
,
445 LPCSTR szTransformFile
, int iErrorCond
)
447 FIXME("%ld %s %d\n", hdb
, debugstr_a(szTransformFile
), iErrorCond
);
448 return ERROR_CALL_NOT_IMPLEMENTED
;
451 UINT WINAPI
MsiDatabaseApplyTransformW( MSIHANDLE hdb
,
452 LPCWSTR szTransformFile
, int iErrorCond
)
454 FIXME("%ld %s %d\n", hdb
, debugstr_w(szTransformFile
), iErrorCond
);
455 return ERROR_CALL_NOT_IMPLEMENTED
;
458 UINT WINAPI
MsiDatabaseGenerateTransformA( MSIHANDLE hdb
, MSIHANDLE hdbref
,
459 LPCSTR szTransformFile
, int iReserved1
, int iReserved2
)
461 FIXME("%ld %ld %s %d %d\n", hdb
, hdbref
,
462 debugstr_a(szTransformFile
), iReserved1
, iReserved2
);
463 return ERROR_CALL_NOT_IMPLEMENTED
;
466 UINT WINAPI
MsiDatabaseGenerateTransformW( MSIHANDLE hdb
, MSIHANDLE hdbref
,
467 LPCWSTR szTransformFile
, int iReserved1
, int iReserved2
)
469 FIXME("%ld %ld %s %d %d\n", hdb
, hdbref
,
470 debugstr_w(szTransformFile
), iReserved1
, iReserved2
);
471 return ERROR_CALL_NOT_IMPLEMENTED
;
474 UINT WINAPI
MsiDatabaseCommit( MSIHANDLE hdb
)
481 db
= msihandle2msiinfo( hdb
, MSIHANDLETYPE_DATABASE
);
483 return ERROR_INVALID_HANDLE
;
485 /* FIXME: lock the database */
487 r
= MSI_CommitTables( db
);
489 /* FIXME: unlock the database */
491 msiobj_release( &db
->hdr
);
496 UINT WINAPI
MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb
,
497 LPCSTR table
, MSIHANDLE
* rec
)
499 FIXME("%ld %s %p\n", hdb
, debugstr_a(table
), rec
);
500 return ERROR_CALL_NOT_IMPLEMENTED
;
503 UINT WINAPI
MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb
,
504 LPCWSTR table
, MSIHANDLE
* rec
)
506 FIXME("%ld %s %p\n", hdb
, debugstr_w(table
), rec
);
507 return ERROR_CALL_NOT_IMPLEMENTED
;
510 UINT WINAPI
MsiViewModify(MSIHANDLE hView
, MSIMODIFY eModifyMode
, MSIHANDLE
513 FIXME("%ld %x %ld\n",hView
, eModifyMode
, hRecord
);
514 return ERROR_CALL_NOT_IMPLEMENTED
;
517 UINT WINAPI
MsiDatabaseIsTablePersistentA(
518 MSIHANDLE hDatabase
, LPSTR szTableName
)
520 FIXME("%lx %s\n", hDatabase
, debugstr_a(szTableName
));
521 return ERROR_CALL_NOT_IMPLEMENTED
;
524 UINT WINAPI
MsiDatabaseIsTablePersistentW(
525 MSIHANDLE hDatabase
, LPWSTR szTableName
)
527 FIXME("%lx %s\n", hDatabase
, debugstr_w(szTableName
));
528 return ERROR_CALL_NOT_IMPLEMENTED
;