Assorted spelling fixes.
[wine] / dlls / msi / record.c
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002 Mike McCormack for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
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"
33
34 #include "query.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(msi);
37
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
43
44 /* maybe we can use a Variant instead of doing it ourselves? */
45 typedef struct tagMSIFIELD
46 {
47     UINT type;
48     union
49     {
50         INT iVal;
51         LPSTR szVal;
52         LPWSTR szwVal;
53         IStream *stream;
54     } u;
55 } MSIFIELD;
56
57 typedef struct tagMSIRECORD
58 {
59     UINT count;       /* as passed to MsiCreateRecord */
60     MSIFIELD fields[1]; /* nb. array size is count+1 */
61 } MSIRECORD;
62
63 void MSI_FreeField( MSIFIELD *field )
64 {
65     switch( field->type )
66     {
67     case MSIFIELD_NULL:
68     case MSIFIELD_INT:
69         break;
70     case MSIFIELD_STR:
71         HeapFree( GetProcessHeap(), 0, field->u.szVal);
72         break;
73     case MSIFIELD_WSTR:
74         HeapFree( GetProcessHeap(), 0, field->u.szwVal);
75         break;
76     case MSIFIELD_STREAM:
77         IStream_Release( field->u.stream );
78         break;
79     default:
80         ERR("Invalid field type %d\n", field->type);
81     }
82 }
83
84 void MSI_CloseRecord( VOID *arg )
85 {
86     MSIRECORD *rec = (MSIRECORD *) arg;
87     UINT i;
88
89     for( i=0; i<rec->count; i++ )
90         MSI_FreeField( &rec->fields[i] );
91 }
92
93 MSIHANDLE WINAPI MsiCreateRecord( unsigned int cParams )
94 {
95     MSIHANDLE handle = 0;
96     UINT sz;
97     MSIRECORD *rec;
98
99     TRACE("%d\n", cParams);
100
101     sz = sizeof (MSIRECORD) + sizeof(MSIFIELD)*(cParams+1) ;
102     handle = alloc_msihandle( MSIHANDLETYPE_RECORD, sz,
103                               MSI_CloseRecord, (void**) &rec );
104     if( !handle )
105         return 0;
106
107     rec->count = cParams;
108
109     return handle;
110 }
111
112 unsigned int WINAPI MsiRecordGetFieldCount( MSIHANDLE handle )
113 {
114     MSIRECORD *rec;
115
116     TRACE("%ld\n", handle );
117
118     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
119     if( !rec )
120     {
121         ERR("Record not found!\n");
122         return 0;
123     }
124
125     return rec->count;
126 }
127
128 static BOOL string2intA( LPCSTR str, int *out )
129 {
130     int x = 0;
131     LPCSTR p = str;
132
133     if( *p == '-' ) /* skip the minus sign */
134         p++;
135     while ( *p )
136     {
137         if( (*p < '0') || (*p > '9') )
138             return FALSE;
139         x *= 10;
140         x += (*p - '0');
141         p++;
142     }
143
144     if( str[0] == '-' ) /* check if it's negative */
145         x = -x;
146     *out = x; 
147
148     return TRUE;
149 }
150
151 static BOOL string2intW( LPCWSTR str, int *out )
152 {
153     int x = 0;
154     LPCWSTR p = str;
155
156     if( *p == '-' ) /* skip the minus sign */
157         p++;
158     while ( *p )
159     {
160         if( (*p < '0') || (*p > '9') )
161             return FALSE;
162         x *= 10;
163         x += (*p - '0');
164         p++;
165     }
166
167     if( str[0] == '-' ) /* check if it's negative */
168         x = -x;
169     *out = x; 
170
171     return TRUE;
172 }
173
174 int WINAPI MsiRecordGetInteger( MSIHANDLE handle, unsigned int iField)
175 {
176     MSIRECORD *rec;
177     int ret = 0;
178
179     TRACE("%ld %d\n", handle, iField );
180
181     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
182     if( !rec )
183         return MSI_NULL_INTEGER;
184
185     if( iField > rec->count )
186         return MSI_NULL_INTEGER;
187
188     switch( rec->fields[iField].type )
189     {
190     case MSIFIELD_INT:
191         return rec->fields[iField].u.iVal;
192     case MSIFIELD_STR:
193         if( string2intA( rec->fields[iField].u.szVal, &ret ) )
194             return ret;
195         return MSI_NULL_INTEGER;
196     case MSIFIELD_WSTR:
197         if( string2intW( rec->fields[iField].u.szwVal, &ret ) )
198             return ret;
199         return MSI_NULL_INTEGER;
200     default:
201         break;
202     }
203
204     return MSI_NULL_INTEGER;
205 }
206
207 UINT WINAPI MsiRecordClearData( MSIHANDLE handle )
208 {
209     MSIRECORD *rec;
210     UINT i;
211
212     TRACE("%ld\n", handle );
213
214     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
215     if( !rec )
216         return ERROR_INVALID_HANDLE;
217
218     for( i=0; i<=rec->count; i++)
219     {
220         MSI_FreeField( &rec->fields[i] );
221         rec->fields[i].type = MSIFIELD_NULL;
222         rec->fields[i].u.iVal = 0;
223     }
224
225     return ERROR_SUCCESS;
226 }
227
228 UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, unsigned int iField, int iVal )
229 {
230     MSIRECORD *rec;
231
232     TRACE("%ld %u %d\n", handle,iField, iVal);
233     
234     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
235     if( !rec )
236         return ERROR_INVALID_HANDLE;
237
238     if( iField <= rec->count )
239     {
240         MSI_FreeField( &rec->fields[iField] );
241         rec->fields[iField].type = MSIFIELD_INT;
242         rec->fields[iField].u.iVal = iVal;
243     }
244
245     return ERROR_SUCCESS;
246 }
247
248 BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, unsigned int iField )
249 {
250     MSIRECORD *rec;
251     BOOL r = TRUE;
252
253     TRACE("%ld %d\n", handle,iField );
254
255     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
256     if( !rec )
257         return ERROR_INVALID_HANDLE;
258
259     r = ( iField > rec->count ) ||
260         ( rec->fields[iField].type == MSIFIELD_NULL );
261
262     return r;
263 }
264
265 UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, unsigned int iField, 
266                LPSTR szValue, DWORD *pcchValue)
267 {
268     MSIRECORD *rec;
269     UINT len=0, ret;
270     CHAR buffer[16];
271
272     TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
273
274     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
275     if( !rec )
276         return ERROR_INVALID_HANDLE;
277
278     if( iField > rec->count )
279         return ERROR_INVALID_PARAMETER;
280
281     ret = ERROR_SUCCESS;
282     switch( rec->fields[iField].type )
283     {
284     case MSIFIELD_INT:
285         wsprintfA(buffer, "%d", rec->fields[iField].u.iVal);
286         len = lstrlenA( buffer );
287         lstrcpynA(szValue, buffer, *pcchValue);
288         break;
289     case MSIFIELD_STR:
290         len = lstrlenA( rec->fields[iField].u.szVal );
291         lstrcpynA(szValue, rec->fields[iField].u.szVal, *pcchValue);
292         break;
293     case MSIFIELD_WSTR:
294         len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
295                              NULL, 0 , NULL, NULL);
296         WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1,
297                              szValue, *pcchValue, NULL, NULL);
298         break;
299     default:
300         ret = ERROR_INVALID_PARAMETER;
301         break;
302     }
303
304     if( *pcchValue < len )
305         ret = ERROR_MORE_DATA;
306     *pcchValue = len;
307
308     return ret;
309 }
310
311 UINT WINAPI MsiRecordGetStringW(MSIHANDLE handle, unsigned int iField,
312                LPWSTR szValue, DWORD *pcchValue)
313 {
314     MSIRECORD *rec;
315     UINT len=0, ret;
316     WCHAR buffer[16];
317     static const WCHAR szFormat[] = { '%','d',0 };
318
319     TRACE("%ld %d %p %p\n", handle, iField, szValue, pcchValue);
320
321     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
322     if( !rec )
323         return ERROR_INVALID_HANDLE;
324
325     if( iField > rec->count )
326         return ERROR_INVALID_PARAMETER;
327
328     ret = ERROR_SUCCESS;
329     switch( rec->fields[iField].type )
330     {
331     case MSIFIELD_INT:
332         wsprintfW(buffer, szFormat, rec->fields[iField].u.iVal);
333         len = lstrlenW( buffer );
334         lstrcpynW(szValue, buffer, *pcchValue);
335         break;
336     case MSIFIELD_WSTR:
337         len = lstrlenW( rec->fields[iField].u.szwVal );
338         lstrcpynW(szValue, rec->fields[iField].u.szwVal, *pcchValue);
339         break;
340     case MSIFIELD_STR:
341         len = MultiByteToWideChar( CP_ACP, 0, rec->fields[iField].u.szVal, -1,
342                              NULL, 0 );
343         MultiByteToWideChar( CP_ACP, 0, rec->fields[iField].u.szVal, -1,
344                              szValue, *pcchValue);
345         break;
346     default:
347         break;
348     }
349
350     if( *pcchValue < len )
351         ret = ERROR_MORE_DATA;
352     *pcchValue = len;
353
354     return ret;
355 }
356
357 UINT WINAPI MsiRecordDataSize(MSIHANDLE hRecord, unsigned int iField)
358 {
359     FIXME("%ld %d\n", hRecord, iField);
360     return 0;
361 }
362
363 UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, unsigned int iField, LPCSTR szValue )
364 {
365     MSIRECORD *rec;
366     LPSTR str;
367
368     TRACE("%ld %d %s\n", handle, iField, debugstr_a(szValue));
369
370     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
371     if( !rec )
372         return ERROR_INVALID_HANDLE;
373
374     if( iField > rec->count )
375         return ERROR_INVALID_FIELD;
376
377     str = HeapAlloc( GetProcessHeap(), 0, (lstrlenA(szValue) + 1)*sizeof str[0]);
378     lstrcpyA( str, szValue );
379
380     MSI_FreeField( &rec->fields[iField] );
381     rec->fields[iField].type = MSIFIELD_STR;
382     rec->fields[iField].u.szVal = str;
383
384     return 0;
385 }
386
387 UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, unsigned int iField, LPCWSTR szValue )
388 {
389     MSIRECORD *rec;
390     LPWSTR str;
391
392     TRACE("%ld %d %s\n", handle, iField, debugstr_w(szValue));
393
394     rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
395     if( !rec )
396         return ERROR_INVALID_HANDLE;
397
398     if( iField > rec->count )
399         return ERROR_INVALID_FIELD;
400
401     str = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(szValue) + 1)*sizeof str[0]);
402     lstrcpyW( str, szValue );
403
404     MSI_FreeField( &rec->fields[iField] );
405     rec->fields[iField].type = MSIFIELD_WSTR;
406     rec->fields[iField].u.szwVal = str;
407
408     return 0;
409 }
410
411 UINT WINAPI MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, LPSTR szResult, DWORD *sz)
412 {
413     FIXME("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz);
414     return ERROR_CALL_NOT_IMPLEMENTED;
415 }
416
417 UINT WINAPI MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, LPWSTR szResult, DWORD *sz)
418 {
419     FIXME("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz);
420     return ERROR_CALL_NOT_IMPLEMENTED;
421 }
422
423 UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, unsigned int iField, LPCSTR szFilename)
424 {
425     FIXME("%ld %d %s\n", hRecord, iField, debugstr_a(szFilename));
426     return ERROR_CALL_NOT_IMPLEMENTED;
427 }
428
429 UINT WINAPI MsiRecordSetStreamW(MSIHANDLE hRecord, unsigned int iField, LPCWSTR szFilename)
430 {
431     FIXME("%ld %d %s\n", hRecord, iField, debugstr_w(szFilename));
432     return ERROR_CALL_NOT_IMPLEMENTED;
433 }
434
435 UINT WINAPI MsiRecordReadStream(MSIHANDLE handle, unsigned int iField, char *buf, DWORD *sz)
436 {
437     FIXME("%ld %d %p %p\n",handle,iField,buf,sz);
438     return ERROR_CALL_NOT_IMPLEMENTED;
439 }