Implemented ProcessComponents.
[wine/testsucceed.git] / dlls / msi / record.c
blobaca62f5a41ac320807a135d9754041427e6516ef
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 <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "winerror.h"
27 #include "wine/debug.h"
28 #include "msi.h"
29 #include "msiquery.h"
30 #include "msipriv.h"
31 #include "objidl.h"
32 #include "winnls.h"
34 #include "query.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msi);
38 #define MSIFIELD_NULL 0
39 #define MSIFIELD_INT 1
40 #define MSIFIELD_STR 2
41 #define MSIFIELD_WSTR 3
42 #define MSIFIELD_STREAM 4
44 /* maybe we can use a Variant instead of doing it ourselves? */
45 typedef struct tagMSIFIELD
47 UINT type;
48 union
50 INT iVal;
51 LPWSTR szwVal;
52 IStream *stream;
53 } u;
54 } MSIFIELD;
56 typedef struct tagMSIRECORD
58 UINT count; /* as passed to MsiCreateRecord */
59 MSIFIELD fields[1]; /* nb. array size is count+1 */
60 } MSIRECORD;
62 void MSI_FreeField( MSIFIELD *field )
64 switch( field->type )
66 case MSIFIELD_NULL:
67 case MSIFIELD_INT:
68 break;
69 case MSIFIELD_WSTR:
70 HeapFree( GetProcessHeap(), 0, field->u.szwVal);
71 break;
72 case MSIFIELD_STREAM:
73 IStream_Release( field->u.stream );
74 break;
75 default:
76 ERR("Invalid field type %d\n", field->type);
80 void MSI_CloseRecord( VOID *arg )
82 MSIRECORD *rec = (MSIRECORD *) arg;
83 UINT i;
85 for( i=0; i<=rec->count; i++ )
86 MSI_FreeField( &rec->fields[i] );
89 MSIHANDLE WINAPI MsiCreateRecord( unsigned int cParams )
91 MSIHANDLE handle = 0;
92 UINT sz;
93 MSIRECORD *rec;
95 TRACE("%d\n", cParams);
97 sz = sizeof (MSIRECORD) + sizeof(MSIFIELD)*(cParams+1) ;
98 handle = alloc_msihandle( MSIHANDLETYPE_RECORD, sz,
99 MSI_CloseRecord, (void**) &rec );
100 if( !handle )
101 return 0;
103 rec->count = cParams;
105 return handle;
108 unsigned int WINAPI MsiRecordGetFieldCount( MSIHANDLE handle )
110 MSIRECORD *rec;
112 TRACE("%ld\n", handle );
114 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
115 if( !rec )
117 ERR("Record not found!\n");
118 return 0;
121 return rec->count;
124 static BOOL string2intW( LPCWSTR str, int *out )
126 int x = 0;
127 LPCWSTR p = str;
129 if( *p == '-' ) /* skip the minus sign */
130 p++;
131 while ( *p )
133 if( (*p < '0') || (*p > '9') )
134 return FALSE;
135 x *= 10;
136 x += (*p - '0');
137 p++;
140 if( str[0] == '-' ) /* check if it's negative */
141 x = -x;
142 *out = x;
144 return TRUE;
147 int WINAPI MsiRecordGetInteger( MSIHANDLE handle, unsigned int iField)
149 MSIRECORD *rec;
150 int ret = 0;
152 TRACE("%ld %d\n", handle, iField );
154 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
155 if( !rec )
156 return MSI_NULL_INTEGER;
158 if( iField > rec->count )
159 return MSI_NULL_INTEGER;
161 switch( rec->fields[iField].type )
163 case MSIFIELD_INT:
164 return rec->fields[iField].u.iVal;
165 case MSIFIELD_WSTR:
166 if( string2intW( rec->fields[iField].u.szwVal, &ret ) )
167 return ret;
168 return MSI_NULL_INTEGER;
169 default:
170 break;
173 return MSI_NULL_INTEGER;
176 UINT WINAPI MsiRecordClearData( MSIHANDLE handle )
178 MSIRECORD *rec;
179 UINT i;
181 TRACE("%ld\n", handle );
183 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
184 if( !rec )
185 return ERROR_INVALID_HANDLE;
187 for( i=0; i<=rec->count; i++)
189 MSI_FreeField( &rec->fields[i] );
190 rec->fields[i].type = MSIFIELD_NULL;
191 rec->fields[i].u.iVal = 0;
194 return ERROR_SUCCESS;
197 UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, unsigned int iField, int iVal )
199 MSIRECORD *rec;
201 TRACE("%ld %u %d\n", handle,iField, iVal);
203 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
204 if( !rec )
205 return ERROR_INVALID_HANDLE;
207 if( iField <= rec->count )
209 MSI_FreeField( &rec->fields[iField] );
210 rec->fields[iField].type = MSIFIELD_INT;
211 rec->fields[iField].u.iVal = iVal;
214 return ERROR_SUCCESS;
217 BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, unsigned int iField )
219 MSIRECORD *rec;
220 BOOL r = TRUE;
222 TRACE("%ld %d\n", handle,iField );
224 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
225 if( !rec )
226 return ERROR_INVALID_HANDLE;
228 r = ( iField > rec->count ) ||
229 ( rec->fields[iField].type == MSIFIELD_NULL );
231 return r;
234 UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, unsigned int iField,
235 LPSTR szValue, DWORD *pcchValue)
237 MSIRECORD *rec;
238 UINT len=0, ret;
239 CHAR buffer[16];
241 TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
243 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
244 if( !rec )
245 return ERROR_INVALID_HANDLE;
247 if( iField > rec->count )
248 return ERROR_INVALID_PARAMETER;
250 ret = ERROR_SUCCESS;
251 switch( rec->fields[iField].type )
253 case MSIFIELD_INT:
254 wsprintfA(buffer, "%d", rec->fields[iField].u.iVal);
255 len = lstrlenA( buffer );
256 lstrcpynA(szValue, buffer, *pcchValue);
257 break;
258 case MSIFIELD_WSTR:
259 len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
260 NULL, 0 , NULL, NULL);
261 WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
262 szValue, *pcchValue, NULL, NULL);
263 break;
264 case MSIFIELD_NULL:
265 len = 1;
266 if( *pcchValue > 0 )
267 szValue[0] = 0;
268 default:
269 ret = ERROR_INVALID_PARAMETER;
270 break;
273 if( *pcchValue < len )
274 ret = ERROR_MORE_DATA;
275 *pcchValue = len;
277 return ret;
280 const WCHAR *MSI_RecordGetString( MSIHANDLE handle, unsigned int iField )
282 MSIRECORD *rec;
284 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
285 if( !rec )
286 return NULL;
288 if( iField > rec->count )
289 return NULL;
291 if( rec->fields[iField].type != MSIFIELD_WSTR )
292 return NULL;
294 return rec->fields[iField].u.szwVal;
297 UINT WINAPI MsiRecordGetStringW(MSIHANDLE handle, unsigned int iField,
298 LPWSTR szValue, DWORD *pcchValue)
300 MSIRECORD *rec;
301 UINT len=0, ret;
302 WCHAR buffer[16];
303 static const WCHAR szFormat[] = { '%','d',0 };
305 TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
307 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
308 if( !rec )
309 return ERROR_INVALID_HANDLE;
311 if( iField > rec->count )
312 return ERROR_INVALID_PARAMETER;
314 ret = ERROR_SUCCESS;
315 switch( rec->fields[iField].type )
317 case MSIFIELD_INT:
318 wsprintfW(buffer, szFormat, rec->fields[iField].u.iVal);
319 len = lstrlenW( buffer );
320 lstrcpynW(szValue, buffer, *pcchValue);
321 break;
322 case MSIFIELD_WSTR:
323 len = lstrlenW( rec->fields[iField].u.szwVal );
324 lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue);
325 break;
326 case MSIFIELD_NULL:
327 len = 1;
328 if( *pcchValue > 0 )
329 szValue[0] = 0;
330 default:
331 break;
334 if( *pcchValue < len )
335 ret = ERROR_MORE_DATA;
336 *pcchValue = len;
338 return ret;
341 UINT WINAPI MsiRecordDataSize(MSIHANDLE hRecord, unsigned int iField)
343 FIXME("%ld %d\n", hRecord, iField);
344 return 0;
347 UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, unsigned int iField, LPCSTR szValue )
349 MSIRECORD *rec;
350 LPWSTR str;
351 UINT len;
353 TRACE("%ld %d %s\n", handle, iField, debugstr_a(szValue));
355 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
356 if( !rec )
357 return ERROR_INVALID_HANDLE;
359 if( iField > rec->count )
360 return ERROR_INVALID_FIELD;
362 len = MultiByteToWideChar( CP_ACP, 0, szValue, -1, NULL, 0 );
363 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
364 MultiByteToWideChar( CP_ACP, 0, szValue, -1, str, len );
365 MSI_FreeField( &rec->fields[iField] );
366 rec->fields[iField].type = MSIFIELD_WSTR;
367 rec->fields[iField].u.szwVal = str;
369 return 0;
372 UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, unsigned int iField, LPCWSTR szValue )
374 MSIRECORD *rec;
375 LPWSTR str;
377 TRACE("%ld %d %s\n", handle, iField, debugstr_w(szValue));
379 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
380 if( !rec )
381 return ERROR_INVALID_HANDLE;
383 if( iField > rec->count )
384 return ERROR_INVALID_FIELD;
386 str = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(szValue) + 1)*sizeof (WCHAR));
387 lstrcpyW( str, szValue );
389 MSI_FreeField( &rec->fields[iField] );
390 rec->fields[iField].type = MSIFIELD_WSTR;
391 rec->fields[iField].u.szwVal = str;
393 return 0;
396 UINT WINAPI MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, LPSTR szResult, DWORD *sz)
398 FIXME("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz);
399 return ERROR_CALL_NOT_IMPLEMENTED;
402 UINT WINAPI MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, LPWSTR szResult, DWORD *sz)
404 FIXME("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz);
405 return ERROR_CALL_NOT_IMPLEMENTED;
408 UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, unsigned int iField, LPCSTR szFilename)
410 FIXME("%ld %d %s\n", hRecord, iField, debugstr_a(szFilename));
411 return ERROR_CALL_NOT_IMPLEMENTED;
414 UINT WINAPI MsiRecordSetStreamW(MSIHANDLE hRecord, unsigned int iField, LPCWSTR szFilename)
416 FIXME("%ld %d %s\n", hRecord, iField, debugstr_w(szFilename));
417 return ERROR_CALL_NOT_IMPLEMENTED;
420 UINT WINAPI MsiRecordReadStream(MSIHANDLE handle, unsigned int iField, char *buf, DWORD *sz)
422 MSIRECORD *rec;
423 ULONG count;
424 HRESULT r;
425 IStream *stm;
427 TRACE("%ld %d %p %p\n", handle, iField, buf, sz);
429 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
430 if( !rec )
431 return ERROR_INVALID_HANDLE;
433 if( iField > rec->count )
434 return ERROR_INVALID_FIELD;
436 if( rec->fields[iField].type != MSIFIELD_STREAM )
437 return ERROR_INVALID_FIELD;
439 stm = rec->fields[iField].u.stream;
440 if( !stm )
441 return ERROR_INVALID_FIELD;
443 /* if there's no buffer pointer, calculate the length to the end */
444 if( !buf )
446 LARGE_INTEGER ofs;
447 ULARGE_INTEGER end, cur;
449 ofs.QuadPart = cur.QuadPart = 0;
450 end.QuadPart = 0;
451 r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur );
452 IStream_Seek( stm, ofs, STREAM_SEEK_END, &end );
453 ofs.QuadPart = cur.QuadPart;
454 IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur );
455 *sz = end.QuadPart - cur.QuadPart;
457 return ERROR_SUCCESS;
460 /* read the data */
461 count = 0;
462 r = IStream_Read( stm, buf, *sz, &count );
463 if( FAILED( r ) )
464 return ERROR_FUNCTION_FAILED;
466 *sz = count;
468 return ERROR_SUCCESS;
471 UINT WINAPI MSI_RecordSetIStream( MSIHANDLE handle, unsigned int iField, IStream *stm )
473 MSIRECORD *rec;
475 TRACE("%ld %d %p\n", handle, iField, stm);
477 rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
478 if( !rec )
479 return ERROR_INVALID_HANDLE;
481 if( iField > rec->count )
482 return ERROR_INVALID_FIELD;
484 MSI_FreeField( &rec->fields[iField] );
486 rec->fields[iField].type = MSIFIELD_STREAM;
487 rec->fields[iField].u.stream = stm;
488 IStream_AddRef( stm );
490 return ERROR_SUCCESS;