Partial implementation of the Microsoft Installer (msi.dll).
[wine/hacks.git] / dlls / msi / msiquery.c
blobac4b3a92515f2eb3d9c54ba29cbc61205ccc217b
1 /*
2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002 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 "windef.h"
22 #include "winbase.h"
23 #include "winerror.h"
24 #include "wine/debug.h"
25 #include "msi.h"
26 #include "msiquery.h"
27 #include "objbase.h"
28 #include "objidl.h"
29 #include "msipriv.h"
30 #include "winnls.h"
32 #include "query.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msi);
36 typedef struct tagMSIQUERY
38 MSIVIEW *view;
39 UINT row;
40 MSIDATABASE *db;
41 } MSIQUERY;
43 UINT WINAPI MsiDatabaseIsTablePersistentA(
44 MSIHANDLE hDatabase, LPSTR szTableName)
46 FIXME("%lx %s\n", hDatabase, debugstr_a(szTableName));
47 return ERROR_CALL_NOT_IMPLEMENTED;
50 UINT WINAPI MsiDatabaseIsTablePersistentW(
51 MSIHANDLE hDatabase, LPWSTR szTableName)
53 FIXME("%lx %s\n", hDatabase, debugstr_w(szTableName));
54 return ERROR_CALL_NOT_IMPLEMENTED;
57 void MSI_CloseView( VOID *arg )
59 MSIQUERY *query = arg;
61 if( query->view && query->view->ops->delete )
62 query->view->ops->delete( query->view );
65 UINT VIEW_find_column( MSIVIEW *table, LPWSTR name, UINT *n )
67 LPWSTR col_name;
68 UINT i, count, r;
70 r = table->ops->get_dimensions( table, NULL, &count );
71 if( r != ERROR_SUCCESS )
72 return r;
74 for( i=1; i<=count; i++ )
76 INT x;
78 col_name = NULL;
79 r = table->ops->get_column_info( table, i, &col_name, NULL );
80 if( r != ERROR_SUCCESS )
81 return r;
82 x = lstrcmpW( name, col_name );
83 HeapFree( GetProcessHeap(), 0, col_name );
84 if( !x )
86 *n = i;
87 return ERROR_SUCCESS;
91 return ERROR_INVALID_PARAMETER;
94 UINT WINAPI MsiDatabaseOpenViewA(MSIHANDLE hdb,
95 LPCSTR szQuery, MSIHANDLE *phView)
97 UINT r;
98 LPCWSTR szwQuery;
100 TRACE("%ld %s %p\n", hdb, debugstr_a(szQuery), phView);
102 if( szQuery )
104 szwQuery = HEAP_strdupAtoW( GetProcessHeap(), 0, szQuery );
105 if( !szwQuery )
106 return ERROR_FUNCTION_FAILED;
108 else
109 szwQuery = NULL;
111 r = MsiDatabaseOpenViewW( hdb, szwQuery, phView);
113 return r;
116 UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb,
117 LPCWSTR szQuery, MSIHANDLE *phView)
119 MSIDATABASE *db;
120 MSIHANDLE handle;
121 MSIQUERY *query;
122 UINT r;
124 TRACE("%s %p\n", debugstr_w(szQuery), phView);
126 if( !szQuery)
127 return ERROR_INVALID_PARAMETER;
129 db = msihandle2msiinfo( hdb, MSIHANDLETYPE_DATABASE );
130 if( !db )
131 return ERROR_INVALID_HANDLE;
133 /* pre allocate a handle to hold a pointer to the view */
134 handle = alloc_msihandle( MSIHANDLETYPE_VIEW, sizeof (MSIQUERY), MSI_CloseView );
135 if( !handle )
136 return ERROR_FUNCTION_FAILED;
137 query = msihandle2msiinfo( handle, MSIHANDLETYPE_VIEW );
138 if( !query )
139 return ERROR_FUNCTION_FAILED;
141 query->row = 0;
142 query->db = db;
143 query->view = NULL;
145 r = MSI_ParseSQL( db, szQuery, &query->view );
146 if( r != ERROR_SUCCESS )
148 MsiCloseHandle( handle );
149 return r;
152 *phView = handle;
154 return ERROR_SUCCESS;
157 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
159 MSIQUERY *query;
160 MSIVIEW *view;
161 MSIHANDLE handle;
162 UINT row_count = 0, col_count = 0, i, ival, ret, type;
164 TRACE("%ld %p\n", hView, record);
166 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
167 if( !query )
168 return ERROR_INVALID_HANDLE;
169 view = query->view;
170 if( !view )
171 return ERROR_FUNCTION_FAILED;
173 ret = view->ops->get_dimensions( view, &row_count, &col_count );
174 if( ret )
175 return ret;
176 if( !col_count )
177 return ERROR_INVALID_PARAMETER;
179 if( query->row >= row_count )
180 return ERROR_NO_MORE_ITEMS;
182 handle = MsiCreateRecord( col_count );
183 if( !handle )
184 return ERROR_FUNCTION_FAILED;
186 for( i=1; i<=col_count; i++ )
188 ret = view->ops->get_column_info( view, i, NULL, &type );
189 if( ret )
191 ERR("Error getting column type for %d\n", i );
192 continue;
194 ret = view->ops->fetch_int( view, query->row, i, &ival );
195 if( ret )
197 ERR("Error fetching data for %d\n", i );
198 continue;
200 if( ! (type & MSITYPE_VALID ) )
201 ERR("Invalid type!\n");
203 /* check if it's nul (0) - if so, don't set anything */
204 if( !ival )
205 continue;
207 if( type & MSITYPE_STRING )
209 LPWSTR sval = MSI_makestring( query->db, ival );
210 MsiRecordSetStringW( handle, i, sval );
211 HeapFree( GetProcessHeap(), 0, sval );
213 else
215 if( (type & MSI_DATASIZEMASK) == 2 )
216 MsiRecordSetInteger( handle, i, ival - (1<<15) );
217 else
218 MsiRecordSetInteger( handle, i, ival - (1<<31) );
221 query->row ++;
223 *record = handle;
225 return ERROR_SUCCESS;
228 UINT WINAPI MsiViewClose(MSIHANDLE hView)
230 MSIQUERY *query;
231 MSIVIEW *view;
233 TRACE("%ld\n", hView );
235 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
236 if( !query )
237 return ERROR_INVALID_HANDLE;
239 view = query->view;
240 if( !view )
241 return ERROR_FUNCTION_FAILED;
242 if( !view->ops->close )
243 return ERROR_FUNCTION_FAILED;
245 return view->ops->close( view );
248 UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRec)
250 MSIQUERY *query;
251 MSIVIEW *view;
253 TRACE("%ld %ld\n", hView, hRec);
255 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
256 if( !query )
257 return ERROR_INVALID_HANDLE;
259 view = query->view;
260 if( !view )
261 return ERROR_FUNCTION_FAILED;
262 if( !view->ops->execute )
263 return ERROR_FUNCTION_FAILED;
264 query->row = 0;
266 return view->ops->execute( view, hRec );
269 UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO info, MSIHANDLE *hRec)
271 MSIVIEW *view;
272 MSIQUERY *query;
273 MSIHANDLE handle;
274 UINT ret, i, count = 0, type;
275 LPWSTR name;
277 TRACE("%ld %d %p\n", hView, info, hRec);
279 query = msihandle2msiinfo( hView, MSIHANDLETYPE_VIEW );
280 if( !query )
281 return ERROR_INVALID_HANDLE;
283 view = query->view;
284 if( !view )
285 return ERROR_FUNCTION_FAILED;
287 if( !view->ops->get_dimensions )
288 return ERROR_FUNCTION_FAILED;
290 ret = view->ops->get_dimensions( view, NULL, &count );
291 if( ret )
292 return ret;
293 if( !count )
294 return ERROR_INVALID_PARAMETER;
296 handle = MsiCreateRecord( count );
297 if( !handle )
298 return ERROR_FUNCTION_FAILED;
300 for( i=0; i<count; i++ )
302 name = NULL;
303 ret = view->ops->get_column_info( view, i+1, &name, &type );
304 if( ret != ERROR_SUCCESS )
305 continue;
306 MsiRecordSetStringW( handle, i+1, name );
307 HeapFree( GetProcessHeap(), 0, name );
310 *hRec = handle;
312 return ERROR_SUCCESS;
316 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
318 FIXME("%ld %s\n", hInstall, debugstr_a(szAction) );
319 return ERROR_CALL_NOT_IMPLEMENTED;
322 UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
324 FIXME("%ld %s\n", hInstall, debugstr_w(szAction) );
325 return ERROR_CALL_NOT_IMPLEMENTED;
328 UINT WINAPI MsiDatabaseApplyTransformA( MSIHANDLE hdb,
329 LPCSTR szTransformFile, int iErrorCond)
331 FIXME("%ld %s %d\n", hdb, debugstr_a(szTransformFile), iErrorCond);
332 return ERROR_CALL_NOT_IMPLEMENTED;
335 UINT WINAPI MsiDatabaseApplyTransformW( MSIHANDLE hdb,
336 LPCWSTR szTransformFile, int iErrorCond)
338 FIXME("%ld %s %d\n", hdb, debugstr_w(szTransformFile), iErrorCond);
339 return ERROR_CALL_NOT_IMPLEMENTED;
342 UINT WINAPI MsiDatabaseGenerateTransformA( MSIHANDLE hdb, MSIHANDLE hdbref,
343 LPCSTR szTransformFile, int iReserved1, int iReserved2 )
345 FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
346 debugstr_a(szTransformFile), iReserved1, iReserved2);
347 return ERROR_CALL_NOT_IMPLEMENTED;
350 UINT WINAPI MsiDatabaseGenerateTransformW( MSIHANDLE hdb, MSIHANDLE hdbref,
351 LPCWSTR szTransformFile, int iReserved1, int iReserved2 )
353 FIXME("%ld %ld %s %d %d\n", hdb, hdbref,
354 debugstr_w(szTransformFile), iReserved1, iReserved2);
355 return ERROR_CALL_NOT_IMPLEMENTED;
358 UINT WINAPI MsiDatabaseCommit( MSIHANDLE hdb )
360 FIXME("%ld\n", hdb);
361 return ERROR_SUCCESS;
364 UINT WINAPI MsiDatabaseGetPrimaryKeysA(MSIHANDLE hdb,
365 LPCSTR table, MSIHANDLE* rec)
367 FIXME("%ld %s %p\n", hdb, debugstr_a(table), rec);
368 return ERROR_CALL_NOT_IMPLEMENTED;
371 UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb,
372 LPCWSTR table, MSIHANDLE* rec)
374 FIXME("%ld %s %p\n", hdb, debugstr_w(table), rec);
375 return ERROR_CALL_NOT_IMPLEMENTED;