1c2c66affSColin Finck /*
2c2c66affSColin Finck * Implementation of the Microsoft Installer (msi.dll)
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2002-2004 Mike McCormack for CodeWeavers
5c2c66affSColin Finck *
6c2c66affSColin Finck * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck * License as published by the Free Software Foundation; either
9c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck *
11c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14c2c66affSColin Finck * Lesser General Public License for more details.
15c2c66affSColin Finck *
16c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck */
20c2c66affSColin Finck
21c42b133eSAmine Khaldi #include <stdarg.h>
22c42b133eSAmine Khaldi
23c42b133eSAmine Khaldi #define COBJMACROS
24c42b133eSAmine Khaldi
25c42b133eSAmine Khaldi #include "windef.h"
26c42b133eSAmine Khaldi #include "winbase.h"
27c42b133eSAmine Khaldi #include "winuser.h"
28c42b133eSAmine Khaldi #include "winerror.h"
29c42b133eSAmine Khaldi #include "wine/debug.h"
30c42b133eSAmine Khaldi #include "msi.h"
31c42b133eSAmine Khaldi #include "msiquery.h"
32c2c66affSColin Finck #include "msipriv.h"
33c42b133eSAmine Khaldi #include "objidl.h"
34c42b133eSAmine Khaldi #include "winnls.h"
35c42b133eSAmine Khaldi #include "ole2.h"
36c42b133eSAmine Khaldi
37c42b133eSAmine Khaldi #include "winreg.h"
38c42b133eSAmine Khaldi #include "shlwapi.h"
39c42b133eSAmine Khaldi
40c42b133eSAmine Khaldi #include "query.h"
41c2c66affSColin Finck
42c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msidb);
43c2c66affSColin Finck
44c2c66affSColin Finck #define MSIFIELD_NULL 0
45c2c66affSColin Finck #define MSIFIELD_INT 1
46c2c66affSColin Finck #define MSIFIELD_WSTR 3
47c2c66affSColin Finck #define MSIFIELD_STREAM 4
48c2c66affSColin Finck
MSI_FreeField(MSIFIELD * field)49c2c66affSColin Finck static void MSI_FreeField( MSIFIELD *field )
50c2c66affSColin Finck {
51c2c66affSColin Finck switch( field->type )
52c2c66affSColin Finck {
53c2c66affSColin Finck case MSIFIELD_NULL:
54c2c66affSColin Finck case MSIFIELD_INT:
55c2c66affSColin Finck break;
56c2c66affSColin Finck case MSIFIELD_WSTR:
57*f4be6dc3SMikhail free( field->u.szwVal);
58c2c66affSColin Finck break;
59c2c66affSColin Finck case MSIFIELD_STREAM:
60c2c66affSColin Finck IStream_Release( field->u.stream );
61c2c66affSColin Finck break;
62c2c66affSColin Finck default:
63c2c66affSColin Finck ERR("Invalid field type %d\n", field->type);
64c2c66affSColin Finck }
65c2c66affSColin Finck }
66c2c66affSColin Finck
MSI_CloseRecord(MSIOBJECTHDR * arg)67c2c66affSColin Finck void MSI_CloseRecord( MSIOBJECTHDR *arg )
68c2c66affSColin Finck {
69c2c66affSColin Finck MSIRECORD *rec = (MSIRECORD *) arg;
70c2c66affSColin Finck UINT i;
71c2c66affSColin Finck
72c2c66affSColin Finck for( i=0; i<=rec->count; i++ )
73c2c66affSColin Finck MSI_FreeField( &rec->fields[i] );
74c2c66affSColin Finck }
75c2c66affSColin Finck
MSI_CreateRecord(UINT cParams)76c2c66affSColin Finck MSIRECORD *MSI_CreateRecord( UINT cParams )
77c2c66affSColin Finck {
78c2c66affSColin Finck MSIRECORD *rec;
79c2c66affSColin Finck
80c2c66affSColin Finck TRACE("%d\n", cParams);
81c2c66affSColin Finck
82c2c66affSColin Finck if( cParams>65535 )
83c2c66affSColin Finck return NULL;
84c2c66affSColin Finck
85c2c66affSColin Finck rec = alloc_msiobject( MSIHANDLETYPE_RECORD, FIELD_OFFSET(MSIRECORD, fields[cParams + 1]),
86c2c66affSColin Finck MSI_CloseRecord );
87c2c66affSColin Finck if( rec )
88c2c66affSColin Finck rec->count = cParams;
89c2c66affSColin Finck return rec;
90c2c66affSColin Finck }
91c2c66affSColin Finck
MsiCreateRecord(UINT cParams)92c2c66affSColin Finck MSIHANDLE WINAPI MsiCreateRecord( UINT cParams )
93c2c66affSColin Finck {
94c2c66affSColin Finck MSIRECORD *rec;
95c2c66affSColin Finck MSIHANDLE ret = 0;
96c2c66affSColin Finck
97c2c66affSColin Finck TRACE("%d\n", cParams);
98c2c66affSColin Finck
99c2c66affSColin Finck rec = MSI_CreateRecord( cParams );
100c2c66affSColin Finck if( rec )
101c2c66affSColin Finck {
102c2c66affSColin Finck ret = alloc_msihandle( &rec->hdr );
103c2c66affSColin Finck msiobj_release( &rec->hdr );
104c2c66affSColin Finck }
105c2c66affSColin Finck return ret;
106c2c66affSColin Finck }
107c2c66affSColin Finck
MSI_RecordGetFieldCount(const MSIRECORD * rec)108c2c66affSColin Finck UINT MSI_RecordGetFieldCount( const MSIRECORD *rec )
109c2c66affSColin Finck {
110c2c66affSColin Finck return rec->count;
111c2c66affSColin Finck }
112c2c66affSColin Finck
MsiRecordGetFieldCount(MSIHANDLE handle)113c2c66affSColin Finck UINT WINAPI MsiRecordGetFieldCount( MSIHANDLE handle )
114c2c66affSColin Finck {
115c2c66affSColin Finck MSIRECORD *rec;
116c2c66affSColin Finck UINT ret;
117c2c66affSColin Finck
11802f995b2Swinesync TRACE( "%lu\n", handle );
119c2c66affSColin Finck
120c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
121c2c66affSColin Finck if( !rec )
122c2c66affSColin Finck return -1;
123c2c66affSColin Finck
124c2c66affSColin Finck msiobj_lock( &rec->hdr );
125c2c66affSColin Finck ret = MSI_RecordGetFieldCount( rec );
126c2c66affSColin Finck msiobj_unlock( &rec->hdr );
127c2c66affSColin Finck msiobj_release( &rec->hdr );
128c2c66affSColin Finck
129c2c66affSColin Finck return ret;
130c2c66affSColin Finck }
131c2c66affSColin Finck
string2intW(LPCWSTR str,int * out)132c2c66affSColin Finck static BOOL string2intW( LPCWSTR str, int *out )
133c2c66affSColin Finck {
134c2c66affSColin Finck int x = 0;
135c2c66affSColin Finck LPCWSTR p = str;
136c2c66affSColin Finck
137c2c66affSColin Finck if( *p == '-' ) /* skip the minus sign */
138c2c66affSColin Finck p++;
139c2c66affSColin Finck while ( *p )
140c2c66affSColin Finck {
141c2c66affSColin Finck if( (*p < '0') || (*p > '9') )
142c2c66affSColin Finck return FALSE;
143c2c66affSColin Finck x *= 10;
144c2c66affSColin Finck x += (*p - '0');
145c2c66affSColin Finck p++;
146c2c66affSColin Finck }
147c2c66affSColin Finck
148c2c66affSColin Finck if( str[0] == '-' ) /* check if it's negative */
149c2c66affSColin Finck x = -x;
150c2c66affSColin Finck *out = x;
151c2c66affSColin Finck
152c2c66affSColin Finck return TRUE;
153c2c66affSColin Finck }
154c2c66affSColin Finck
msi_strdupW(const WCHAR * value,int len)155c2c66affSColin Finck WCHAR *msi_strdupW( const WCHAR *value, int len )
156c2c66affSColin Finck {
157c2c66affSColin Finck WCHAR *ret;
158c2c66affSColin Finck
159c2c66affSColin Finck if (!value) return NULL;
160*f4be6dc3SMikhail if (!(ret = malloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
161c2c66affSColin Finck memcpy( ret, value, len * sizeof(WCHAR) );
162c2c66affSColin Finck ret[len] = 0;
163c2c66affSColin Finck return ret;
164c2c66affSColin Finck }
165c2c66affSColin Finck
MSI_RecordCopyField(MSIRECORD * in_rec,UINT in_n,MSIRECORD * out_rec,UINT out_n)166c2c66affSColin Finck UINT MSI_RecordCopyField( MSIRECORD *in_rec, UINT in_n,
167c2c66affSColin Finck MSIRECORD *out_rec, UINT out_n )
168c2c66affSColin Finck {
169c2c66affSColin Finck UINT r = ERROR_SUCCESS;
170c2c66affSColin Finck
171c2c66affSColin Finck msiobj_lock( &in_rec->hdr );
172c2c66affSColin Finck
173c2c66affSColin Finck if ( in_n > in_rec->count || out_n > out_rec->count )
174c2c66affSColin Finck r = ERROR_FUNCTION_FAILED;
175c2c66affSColin Finck else if ( in_rec != out_rec || in_n != out_n )
176c2c66affSColin Finck {
177c2c66affSColin Finck LPWSTR str;
178c2c66affSColin Finck MSIFIELD *in, *out;
179c2c66affSColin Finck
180c2c66affSColin Finck in = &in_rec->fields[in_n];
181c2c66affSColin Finck out = &out_rec->fields[out_n];
182c2c66affSColin Finck
183c2c66affSColin Finck switch ( in->type )
184c2c66affSColin Finck {
185c2c66affSColin Finck case MSIFIELD_NULL:
186c2c66affSColin Finck break;
187c2c66affSColin Finck case MSIFIELD_INT:
188c2c66affSColin Finck out->u.iVal = in->u.iVal;
189c2c66affSColin Finck break;
190c2c66affSColin Finck case MSIFIELD_WSTR:
191c2c66affSColin Finck if ((str = msi_strdupW( in->u.szwVal, in->len )))
192c2c66affSColin Finck {
193c2c66affSColin Finck out->u.szwVal = str;
194c2c66affSColin Finck out->len = in->len;
195c2c66affSColin Finck }
196c2c66affSColin Finck else r = ERROR_OUTOFMEMORY;
197c2c66affSColin Finck break;
198c2c66affSColin Finck case MSIFIELD_STREAM:
199c2c66affSColin Finck IStream_AddRef( in->u.stream );
200c2c66affSColin Finck out->u.stream = in->u.stream;
201c2c66affSColin Finck break;
202c2c66affSColin Finck default:
203c2c66affSColin Finck ERR("invalid field type %d\n", in->type);
204c2c66affSColin Finck }
205c2c66affSColin Finck if (r == ERROR_SUCCESS)
206c2c66affSColin Finck out->type = in->type;
207c2c66affSColin Finck }
208c2c66affSColin Finck
209c2c66affSColin Finck msiobj_unlock( &in_rec->hdr );
210c2c66affSColin Finck return r;
211c2c66affSColin Finck }
212c2c66affSColin Finck
MSI_RecordGetInteger(MSIRECORD * rec,UINT iField)213c2c66affSColin Finck int MSI_RecordGetInteger( MSIRECORD *rec, UINT iField)
214c2c66affSColin Finck {
215c2c66affSColin Finck int ret = 0;
216c2c66affSColin Finck
217c2c66affSColin Finck TRACE("%p %d\n", rec, iField );
218c2c66affSColin Finck
219c2c66affSColin Finck if( iField > rec->count )
220c2c66affSColin Finck return MSI_NULL_INTEGER;
221c2c66affSColin Finck
222c2c66affSColin Finck switch( rec->fields[iField].type )
223c2c66affSColin Finck {
224c2c66affSColin Finck case MSIFIELD_INT:
225c2c66affSColin Finck return rec->fields[iField].u.iVal;
226c2c66affSColin Finck case MSIFIELD_WSTR:
227c2c66affSColin Finck if( string2intW( rec->fields[iField].u.szwVal, &ret ) )
228c2c66affSColin Finck return ret;
229c2c66affSColin Finck return MSI_NULL_INTEGER;
230c2c66affSColin Finck default:
231c2c66affSColin Finck break;
232c2c66affSColin Finck }
233c2c66affSColin Finck
234c2c66affSColin Finck return MSI_NULL_INTEGER;
235c2c66affSColin Finck }
236c2c66affSColin Finck
MsiRecordGetInteger(MSIHANDLE handle,UINT iField)237c2c66affSColin Finck int WINAPI MsiRecordGetInteger( MSIHANDLE handle, UINT iField)
238c2c66affSColin Finck {
239c2c66affSColin Finck MSIRECORD *rec;
240c2c66affSColin Finck UINT ret;
241c2c66affSColin Finck
24202f995b2Swinesync TRACE( "%lu, %u\n", handle, iField );
243c2c66affSColin Finck
244c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
245c2c66affSColin Finck if( !rec )
246c2c66affSColin Finck return MSI_NULL_INTEGER;
247c2c66affSColin Finck
248c2c66affSColin Finck msiobj_lock( &rec->hdr );
249c2c66affSColin Finck ret = MSI_RecordGetInteger( rec, iField );
250c2c66affSColin Finck msiobj_unlock( &rec->hdr );
251c2c66affSColin Finck msiobj_release( &rec->hdr );
252c2c66affSColin Finck
253c2c66affSColin Finck return ret;
254c2c66affSColin Finck }
255c2c66affSColin Finck
MsiRecordClearData(MSIHANDLE handle)256c2c66affSColin Finck UINT WINAPI MsiRecordClearData( MSIHANDLE handle )
257c2c66affSColin Finck {
258c2c66affSColin Finck MSIRECORD *rec;
259c2c66affSColin Finck UINT i;
260c2c66affSColin Finck
26102f995b2Swinesync TRACE( "%lu\n", handle );
262c2c66affSColin Finck
263c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
264c2c66affSColin Finck if( !rec )
265c2c66affSColin Finck return ERROR_INVALID_HANDLE;
266c2c66affSColin Finck
267c2c66affSColin Finck msiobj_lock( &rec->hdr );
268c2c66affSColin Finck for( i=0; i<=rec->count; i++)
269c2c66affSColin Finck {
270c2c66affSColin Finck MSI_FreeField( &rec->fields[i] );
271c2c66affSColin Finck rec->fields[i].type = MSIFIELD_NULL;
272c2c66affSColin Finck rec->fields[i].u.iVal = 0;
273c2c66affSColin Finck }
274c2c66affSColin Finck msiobj_unlock( &rec->hdr );
275c2c66affSColin Finck msiobj_release( &rec->hdr );
276c2c66affSColin Finck
277c2c66affSColin Finck return ERROR_SUCCESS;
278c2c66affSColin Finck }
279c2c66affSColin Finck
MSI_RecordSetInteger(MSIRECORD * rec,UINT iField,int iVal)280c2c66affSColin Finck UINT MSI_RecordSetInteger( MSIRECORD *rec, UINT iField, int iVal )
281c2c66affSColin Finck {
282c2c66affSColin Finck TRACE("%p %u %d\n", rec, iField, iVal);
283c2c66affSColin Finck
284c2c66affSColin Finck if( iField > rec->count )
285c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
286c2c66affSColin Finck
287c2c66affSColin Finck MSI_FreeField( &rec->fields[iField] );
28871bffdcdSAmine Khaldi
28971bffdcdSAmine Khaldi if (iVal == MSI_NULL_INTEGER)
29071bffdcdSAmine Khaldi {
29171bffdcdSAmine Khaldi rec->fields[iField].type = MSIFIELD_NULL;
29271bffdcdSAmine Khaldi rec->fields[iField].u.szwVal = NULL;
29371bffdcdSAmine Khaldi }
29471bffdcdSAmine Khaldi else
29571bffdcdSAmine Khaldi {
296c2c66affSColin Finck rec->fields[iField].type = MSIFIELD_INT;
297c2c66affSColin Finck rec->fields[iField].u.iVal = iVal;
29871bffdcdSAmine Khaldi }
299c2c66affSColin Finck
300c2c66affSColin Finck return ERROR_SUCCESS;
301c2c66affSColin Finck }
302c2c66affSColin Finck
MsiRecordSetInteger(MSIHANDLE handle,UINT iField,int iVal)303c2c66affSColin Finck UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, UINT iField, int iVal )
304c2c66affSColin Finck {
305c2c66affSColin Finck MSIRECORD *rec;
306c2c66affSColin Finck UINT ret;
307c2c66affSColin Finck
30802f995b2Swinesync TRACE( "%lu, %u, %d\n", handle, iField, iVal );
309c2c66affSColin Finck
310c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
311c2c66affSColin Finck if( !rec )
312c2c66affSColin Finck return ERROR_INVALID_HANDLE;
313c2c66affSColin Finck
314c2c66affSColin Finck msiobj_lock( &rec->hdr );
315c2c66affSColin Finck ret = MSI_RecordSetInteger( rec, iField, iVal );
316c2c66affSColin Finck msiobj_unlock( &rec->hdr );
317c2c66affSColin Finck msiobj_release( &rec->hdr );
318c2c66affSColin Finck return ret;
319c2c66affSColin Finck }
320c2c66affSColin Finck
MSI_RecordIsNull(MSIRECORD * rec,UINT iField)321c2c66affSColin Finck BOOL MSI_RecordIsNull( MSIRECORD *rec, UINT iField )
322c2c66affSColin Finck {
323c2c66affSColin Finck BOOL r = TRUE;
324c2c66affSColin Finck
325c2c66affSColin Finck TRACE("%p %d\n", rec, iField );
326c2c66affSColin Finck
327c2c66affSColin Finck r = ( iField > rec->count ) ||
328c2c66affSColin Finck ( rec->fields[iField].type == MSIFIELD_NULL );
329c2c66affSColin Finck
330c2c66affSColin Finck return r;
331c2c66affSColin Finck }
332c2c66affSColin Finck
MsiRecordIsNull(MSIHANDLE handle,UINT iField)333c2c66affSColin Finck BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, UINT iField )
334c2c66affSColin Finck {
335c2c66affSColin Finck MSIRECORD *rec;
336c2c66affSColin Finck UINT ret;
337c2c66affSColin Finck
33802f995b2Swinesync TRACE( "%lu, %u\n", handle, iField );
339c2c66affSColin Finck
340c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
341c2c66affSColin Finck if( !rec )
342c2c66affSColin Finck return FALSE;
343c2c66affSColin Finck msiobj_lock( &rec->hdr );
344c2c66affSColin Finck ret = MSI_RecordIsNull( rec, iField );
345c2c66affSColin Finck msiobj_unlock( &rec->hdr );
346c2c66affSColin Finck msiobj_release( &rec->hdr );
347c2c66affSColin Finck return ret;
348c2c66affSColin Finck
349c2c66affSColin Finck }
350c2c66affSColin Finck
MSI_RecordGetStringA(MSIRECORD * rec,UINT iField,LPSTR szValue,LPDWORD pcchValue)351c2c66affSColin Finck UINT MSI_RecordGetStringA(MSIRECORD *rec, UINT iField,
352c2c66affSColin Finck LPSTR szValue, LPDWORD pcchValue)
353c2c66affSColin Finck {
354c2c66affSColin Finck UINT len = 0, ret = ERROR_SUCCESS;
355c2c66affSColin Finck CHAR buffer[16];
356c2c66affSColin Finck
357c2c66affSColin Finck TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue);
358c2c66affSColin Finck
359c2c66affSColin Finck if( iField > rec->count )
360c2c66affSColin Finck {
361c2c66affSColin Finck if ( szValue && *pcchValue > 0 )
362c2c66affSColin Finck szValue[0] = 0;
363c2c66affSColin Finck
364c2c66affSColin Finck *pcchValue = 0;
365c2c66affSColin Finck return ERROR_SUCCESS;
366c2c66affSColin Finck }
367c2c66affSColin Finck
368c2c66affSColin Finck switch( rec->fields[iField].type )
369c2c66affSColin Finck {
370c2c66affSColin Finck case MSIFIELD_INT:
371c2c66affSColin Finck wsprintfA(buffer, "%d", rec->fields[iField].u.iVal);
372c2c66affSColin Finck len = lstrlenA( buffer );
373c2c66affSColin Finck if (szValue)
374c2c66affSColin Finck lstrcpynA(szValue, buffer, *pcchValue);
375c2c66affSColin Finck break;
376c2c66affSColin Finck case MSIFIELD_WSTR:
377c2c66affSColin Finck len = WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
378c2c66affSColin Finck rec->fields[iField].len + 1, NULL, 0 , NULL, NULL );
379c2c66affSColin Finck if (szValue)
380c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal,
381c2c66affSColin Finck rec->fields[iField].len + 1, szValue, *pcchValue, NULL, NULL );
382c2c66affSColin Finck if( szValue && *pcchValue && len>*pcchValue )
383c2c66affSColin Finck szValue[*pcchValue-1] = 0;
384c2c66affSColin Finck if( len )
385c2c66affSColin Finck len--;
386c2c66affSColin Finck break;
387c2c66affSColin Finck case MSIFIELD_NULL:
388c2c66affSColin Finck if( szValue && *pcchValue > 0 )
389c2c66affSColin Finck szValue[0] = 0;
390c2c66affSColin Finck break;
391c2c66affSColin Finck default:
392c2c66affSColin Finck ret = ERROR_INVALID_PARAMETER;
393c2c66affSColin Finck break;
394c2c66affSColin Finck }
395c2c66affSColin Finck
396c2c66affSColin Finck if( szValue && *pcchValue <= len )
397c2c66affSColin Finck ret = ERROR_MORE_DATA;
398c2c66affSColin Finck *pcchValue = len;
399c2c66affSColin Finck
400c2c66affSColin Finck return ret;
401c2c66affSColin Finck }
402c2c66affSColin Finck
MsiRecordGetStringA(MSIHANDLE handle,UINT iField,char * szValue,DWORD * pcchValue)40302f995b2Swinesync UINT WINAPI MsiRecordGetStringA( MSIHANDLE handle, UINT iField, char *szValue, DWORD *pcchValue )
404c2c66affSColin Finck {
405c2c66affSColin Finck MSIRECORD *rec;
406c2c66affSColin Finck UINT ret;
407c2c66affSColin Finck
40802f995b2Swinesync TRACE( "%lu, %d, %p, %p\n", handle, iField, szValue, pcchValue );
409c2c66affSColin Finck
410c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
411c2c66affSColin Finck if( !rec )
412c2c66affSColin Finck return ERROR_INVALID_HANDLE;
413c2c66affSColin Finck msiobj_lock( &rec->hdr );
414c2c66affSColin Finck ret = MSI_RecordGetStringA( rec, iField, szValue, pcchValue);
415c2c66affSColin Finck msiobj_unlock( &rec->hdr );
416c2c66affSColin Finck msiobj_release( &rec->hdr );
417c2c66affSColin Finck return ret;
418c2c66affSColin Finck }
419c2c66affSColin Finck
msi_record_get_string(const MSIRECORD * rec,UINT field,int * len)420c2c66affSColin Finck const WCHAR *msi_record_get_string( const MSIRECORD *rec, UINT field, int *len )
421c2c66affSColin Finck {
422c2c66affSColin Finck if (field > rec->count)
423c2c66affSColin Finck return NULL;
424c2c66affSColin Finck
425c2c66affSColin Finck if (rec->fields[field].type != MSIFIELD_WSTR)
426c2c66affSColin Finck return NULL;
427c2c66affSColin Finck
428c2c66affSColin Finck if (len) *len = rec->fields[field].len;
429c2c66affSColin Finck
430c2c66affSColin Finck return rec->fields[field].u.szwVal;
431c2c66affSColin Finck }
432c2c66affSColin Finck
MSI_RecordGetString(const MSIRECORD * rec,UINT iField)433c2c66affSColin Finck const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField )
434c2c66affSColin Finck {
435c2c66affSColin Finck return msi_record_get_string( rec, iField, NULL );
436c2c66affSColin Finck }
437c2c66affSColin Finck
MSI_RecordGetStringW(MSIRECORD * rec,UINT iField,WCHAR * szValue,DWORD * pcchValue)43802f995b2Swinesync UINT MSI_RecordGetStringW( MSIRECORD *rec, UINT iField, WCHAR *szValue, DWORD *pcchValue )
439c2c66affSColin Finck {
440c2c66affSColin Finck UINT len = 0, ret = ERROR_SUCCESS;
441c2c66affSColin Finck WCHAR buffer[16];
442c2c66affSColin Finck
44302f995b2Swinesync TRACE( "%p, %u, %p, %p\n", rec, iField, szValue, pcchValue );
444c2c66affSColin Finck
445c2c66affSColin Finck if( iField > rec->count )
446c2c66affSColin Finck {
447c2c66affSColin Finck if ( szValue && *pcchValue > 0 )
448c2c66affSColin Finck szValue[0] = 0;
449c2c66affSColin Finck
450c2c66affSColin Finck *pcchValue = 0;
451c2c66affSColin Finck return ERROR_SUCCESS;
452c2c66affSColin Finck }
453c2c66affSColin Finck
454c2c66affSColin Finck switch( rec->fields[iField].type )
455c2c66affSColin Finck {
456c2c66affSColin Finck case MSIFIELD_INT:
45774f53b4bSwinesync wsprintfW(buffer, L"%d", rec->fields[iField].u.iVal);
458c2c66affSColin Finck len = lstrlenW( buffer );
459c2c66affSColin Finck if (szValue)
460c2c66affSColin Finck lstrcpynW(szValue, buffer, *pcchValue);
461c2c66affSColin Finck break;
462c2c66affSColin Finck case MSIFIELD_WSTR:
463c2c66affSColin Finck len = rec->fields[iField].len;
464c2c66affSColin Finck if (szValue)
465c2c66affSColin Finck memcpy( szValue, rec->fields[iField].u.szwVal, min(len + 1, *pcchValue) * sizeof(WCHAR) );
466c2c66affSColin Finck break;
467c2c66affSColin Finck case MSIFIELD_NULL:
468c2c66affSColin Finck if( szValue && *pcchValue > 0 )
469c2c66affSColin Finck szValue[0] = 0;
470c2c66affSColin Finck break;
471c2c66affSColin Finck default:
472c2c66affSColin Finck break;
473c2c66affSColin Finck }
474c2c66affSColin Finck
475c2c66affSColin Finck if( szValue && *pcchValue <= len )
476c2c66affSColin Finck ret = ERROR_MORE_DATA;
477c2c66affSColin Finck *pcchValue = len;
478c2c66affSColin Finck
479c2c66affSColin Finck return ret;
480c2c66affSColin Finck }
481c2c66affSColin Finck
MsiRecordGetStringW(MSIHANDLE handle,UINT iField,WCHAR * szValue,DWORD * pcchValue)48202f995b2Swinesync UINT WINAPI MsiRecordGetStringW( MSIHANDLE handle, UINT iField, WCHAR *szValue, DWORD *pcchValue )
483c2c66affSColin Finck {
484c2c66affSColin Finck MSIRECORD *rec;
485c2c66affSColin Finck UINT ret;
486c2c66affSColin Finck
48702f995b2Swinesync TRACE( "%lu, %u, %p, %p\n", handle, iField, szValue, pcchValue );
488c2c66affSColin Finck
489c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
490c2c66affSColin Finck if( !rec )
491c2c66affSColin Finck return ERROR_INVALID_HANDLE;
492c2c66affSColin Finck
493c2c66affSColin Finck msiobj_lock( &rec->hdr );
494c2c66affSColin Finck ret = MSI_RecordGetStringW( rec, iField, szValue, pcchValue );
495c2c66affSColin Finck msiobj_unlock( &rec->hdr );
496c2c66affSColin Finck msiobj_release( &rec->hdr );
497c2c66affSColin Finck return ret;
498c2c66affSColin Finck }
499c2c66affSColin Finck
get_stream_size(IStream * stm)500*f4be6dc3SMikhail static UINT get_stream_size( IStream *stm )
501c2c66affSColin Finck {
502c2c66affSColin Finck STATSTG stat;
503c2c66affSColin Finck HRESULT r;
504c2c66affSColin Finck
505c2c66affSColin Finck r = IStream_Stat( stm, &stat, STATFLAG_NONAME );
506c2c66affSColin Finck if( FAILED(r) )
507c2c66affSColin Finck return 0;
508c2c66affSColin Finck return stat.cbSize.QuadPart;
509c2c66affSColin Finck }
510c2c66affSColin Finck
MSI_RecordDataSize(MSIRECORD * rec,UINT iField)511c2c66affSColin Finck static UINT MSI_RecordDataSize(MSIRECORD *rec, UINT iField)
512c2c66affSColin Finck {
513c2c66affSColin Finck TRACE("%p %d\n", rec, iField);
514c2c66affSColin Finck
515c2c66affSColin Finck if( iField > rec->count )
516c2c66affSColin Finck return 0;
517c2c66affSColin Finck
518c2c66affSColin Finck switch( rec->fields[iField].type )
519c2c66affSColin Finck {
520c2c66affSColin Finck case MSIFIELD_INT:
521c2c66affSColin Finck return sizeof (INT);
522c2c66affSColin Finck case MSIFIELD_WSTR:
523c2c66affSColin Finck return rec->fields[iField].len;
524c2c66affSColin Finck case MSIFIELD_NULL:
525c2c66affSColin Finck break;
526c2c66affSColin Finck case MSIFIELD_STREAM:
527*f4be6dc3SMikhail return get_stream_size( rec->fields[iField].u.stream );
528c2c66affSColin Finck }
529c2c66affSColin Finck return 0;
530c2c66affSColin Finck }
531c2c66affSColin Finck
MsiRecordDataSize(MSIHANDLE handle,UINT iField)532c2c66affSColin Finck UINT WINAPI MsiRecordDataSize( MSIHANDLE handle, UINT iField )
533c2c66affSColin Finck {
534c2c66affSColin Finck MSIRECORD *rec;
535c2c66affSColin Finck UINT ret;
536c2c66affSColin Finck
53702f995b2Swinesync TRACE( "%lu, %u\n", handle, iField );
538c2c66affSColin Finck
539c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
540c2c66affSColin Finck if( !rec )
541c2c66affSColin Finck return 0;
542c2c66affSColin Finck msiobj_lock( &rec->hdr );
543c2c66affSColin Finck ret = MSI_RecordDataSize( rec, iField);
544c2c66affSColin Finck msiobj_unlock( &rec->hdr );
545c2c66affSColin Finck msiobj_release( &rec->hdr );
546c2c66affSColin Finck return ret;
547c2c66affSColin Finck }
548c2c66affSColin Finck
MsiRecordSetStringA(MSIHANDLE handle,UINT iField,const char * szValue)54902f995b2Swinesync UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, UINT iField, const char *szValue )
550c2c66affSColin Finck {
551c2c66affSColin Finck WCHAR *valueW = NULL;
552c2c66affSColin Finck MSIRECORD *rec;
553c2c66affSColin Finck UINT ret;
554c2c66affSColin Finck
55502f995b2Swinesync TRACE( "%lu, %u %s\n", handle, iField, debugstr_a(szValue) );
556c2c66affSColin Finck
557c2c66affSColin Finck if (szValue && !(valueW = strdupAtoW( szValue ))) return ERROR_OUTOFMEMORY;
558c2c66affSColin Finck
559c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
560c2c66affSColin Finck if( !rec )
561c2c66affSColin Finck {
562*f4be6dc3SMikhail free( valueW );
563c2c66affSColin Finck return ERROR_INVALID_HANDLE;
564c2c66affSColin Finck }
565c2c66affSColin Finck msiobj_lock( &rec->hdr );
566c2c66affSColin Finck ret = MSI_RecordSetStringW( rec, iField, valueW );
567c2c66affSColin Finck msiobj_unlock( &rec->hdr );
568c2c66affSColin Finck msiobj_release( &rec->hdr );
569*f4be6dc3SMikhail free( valueW );
570c2c66affSColin Finck return ret;
571c2c66affSColin Finck }
572c2c66affSColin Finck
msi_record_set_string(MSIRECORD * rec,UINT field,const WCHAR * value,int len)573c2c66affSColin Finck UINT msi_record_set_string( MSIRECORD *rec, UINT field, const WCHAR *value, int len )
574c2c66affSColin Finck {
575c2c66affSColin Finck if (field > rec->count)
576c2c66affSColin Finck return ERROR_INVALID_FIELD;
577c2c66affSColin Finck
578c2c66affSColin Finck MSI_FreeField( &rec->fields[field] );
579c2c66affSColin Finck
580958f1addSwinesync if (value && len < 0) len = lstrlenW( value );
581c2c66affSColin Finck
582c2c66affSColin Finck if (value && len)
583c2c66affSColin Finck {
584c2c66affSColin Finck rec->fields[field].type = MSIFIELD_WSTR;
585c2c66affSColin Finck rec->fields[field].u.szwVal = msi_strdupW( value, len );
586c2c66affSColin Finck rec->fields[field].len = len;
587c2c66affSColin Finck }
588c2c66affSColin Finck else
589c2c66affSColin Finck {
590c2c66affSColin Finck rec->fields[field].type = MSIFIELD_NULL;
591c2c66affSColin Finck rec->fields[field].u.szwVal = NULL;
592c2c66affSColin Finck rec->fields[field].len = 0;
593c2c66affSColin Finck }
594c2c66affSColin Finck return 0;
595c2c66affSColin Finck }
596c2c66affSColin Finck
MSI_RecordSetStringW(MSIRECORD * rec,UINT iField,LPCWSTR szValue)597c2c66affSColin Finck UINT MSI_RecordSetStringW( MSIRECORD *rec, UINT iField, LPCWSTR szValue )
598c2c66affSColin Finck {
599c2c66affSColin Finck TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue));
600c2c66affSColin Finck
601c2c66affSColin Finck return msi_record_set_string( rec, iField, szValue, -1 );
602c2c66affSColin Finck }
603c2c66affSColin Finck
MsiRecordSetStringW(MSIHANDLE handle,UINT iField,const WCHAR * szValue)60402f995b2Swinesync UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, UINT iField, const WCHAR *szValue )
605c2c66affSColin Finck {
606c2c66affSColin Finck MSIRECORD *rec;
607c2c66affSColin Finck UINT ret;
608c2c66affSColin Finck
60902f995b2Swinesync TRACE( "%lu, %u, %s\n", handle, iField, debugstr_w(szValue) );
610c2c66affSColin Finck
611c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
612c2c66affSColin Finck if( !rec )
613c2c66affSColin Finck return ERROR_INVALID_HANDLE;
614c2c66affSColin Finck
615c2c66affSColin Finck msiobj_lock( &rec->hdr );
616c2c66affSColin Finck ret = MSI_RecordSetStringW( rec, iField, szValue );
617c2c66affSColin Finck msiobj_unlock( &rec->hdr );
618c2c66affSColin Finck msiobj_release( &rec->hdr );
619c2c66affSColin Finck return ret;
620c2c66affSColin Finck }
621c2c66affSColin Finck
622c2c66affSColin Finck /* read the data in a file into an IStream */
RECORD_StreamFromFile(LPCWSTR szFile,IStream ** pstm)623c2c66affSColin Finck static UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm)
624c2c66affSColin Finck {
625c2c66affSColin Finck DWORD sz, szHighWord = 0, read;
626c2c66affSColin Finck HANDLE handle;
627c2c66affSColin Finck HGLOBAL hGlob = 0;
628c2c66affSColin Finck HRESULT hr;
629c2c66affSColin Finck ULARGE_INTEGER ulSize;
630c2c66affSColin Finck
631c2c66affSColin Finck TRACE("reading %s\n", debugstr_w(szFile));
632c2c66affSColin Finck
633c2c66affSColin Finck /* read the file into memory */
634c2c66affSColin Finck handle = CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
635c2c66affSColin Finck if( handle == INVALID_HANDLE_VALUE )
636c2c66affSColin Finck return GetLastError();
637c2c66affSColin Finck sz = GetFileSize(handle, &szHighWord);
638c2c66affSColin Finck if( sz != INVALID_FILE_SIZE && szHighWord == 0 )
639c2c66affSColin Finck {
640c2c66affSColin Finck hGlob = GlobalAlloc(GMEM_FIXED, sz);
641c2c66affSColin Finck if( hGlob )
642c2c66affSColin Finck {
643c2c66affSColin Finck BOOL r = ReadFile(handle, hGlob, sz, &read, NULL) && read == sz;
644c2c66affSColin Finck if( !r )
645c2c66affSColin Finck {
646c2c66affSColin Finck GlobalFree(hGlob);
647c2c66affSColin Finck hGlob = 0;
648c2c66affSColin Finck }
649c2c66affSColin Finck }
650c2c66affSColin Finck }
651c2c66affSColin Finck CloseHandle(handle);
652c2c66affSColin Finck if( !hGlob )
653c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
654c2c66affSColin Finck
655c2c66affSColin Finck /* make a stream out of it, and set the correct file size */
656c2c66affSColin Finck hr = CreateStreamOnHGlobal(hGlob, TRUE, pstm);
657c2c66affSColin Finck if( FAILED( hr ) )
658c2c66affSColin Finck {
659c2c66affSColin Finck GlobalFree(hGlob);
660c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
661c2c66affSColin Finck }
662c2c66affSColin Finck
663c2c66affSColin Finck /* set the correct size - CreateStreamOnHGlobal screws it up */
664c2c66affSColin Finck ulSize.QuadPart = sz;
665c2c66affSColin Finck IStream_SetSize(*pstm, ulSize);
666c2c66affSColin Finck
66702f995b2Swinesync TRACE( "read %s, %lu bytes into IStream %p\n", debugstr_w(szFile), sz, *pstm );
668c2c66affSColin Finck return ERROR_SUCCESS;
669c2c66affSColin Finck }
670c2c66affSColin Finck
MSI_RecordSetStream(MSIRECORD * rec,UINT iField,IStream * stream)671c2c66affSColin Finck UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream)
672c2c66affSColin Finck {
673c2c66affSColin Finck if ( (iField == 0) || (iField > rec->count) )
674c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
675c2c66affSColin Finck
676c2c66affSColin Finck MSI_FreeField( &rec->fields[iField] );
677c2c66affSColin Finck rec->fields[iField].type = MSIFIELD_STREAM;
678c2c66affSColin Finck rec->fields[iField].u.stream = stream;
679c2c66affSColin Finck
680c2c66affSColin Finck return ERROR_SUCCESS;
681c2c66affSColin Finck }
682c2c66affSColin Finck
MSI_RecordSetStreamFromFileW(MSIRECORD * rec,UINT iField,LPCWSTR szFilename)683c2c66affSColin Finck UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename)
684c2c66affSColin Finck {
685c2c66affSColin Finck IStream *stm = NULL;
686c2c66affSColin Finck HRESULT hr;
687c2c66affSColin Finck UINT ret;
688c2c66affSColin Finck
689c2c66affSColin Finck if( (iField == 0) || (iField > rec->count) )
690c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
691c2c66affSColin Finck
692c2c66affSColin Finck /* no filename means we should seek back to the start of the stream */
693c2c66affSColin Finck if( !szFilename )
694c2c66affSColin Finck {
695c2c66affSColin Finck LARGE_INTEGER ofs;
696c2c66affSColin Finck ULARGE_INTEGER cur;
697c2c66affSColin Finck
698c2c66affSColin Finck if( rec->fields[iField].type != MSIFIELD_STREAM )
699c2c66affSColin Finck return ERROR_INVALID_FIELD;
700c2c66affSColin Finck
701c2c66affSColin Finck stm = rec->fields[iField].u.stream;
702c2c66affSColin Finck if( !stm )
703c2c66affSColin Finck return ERROR_INVALID_FIELD;
704c2c66affSColin Finck
705c2c66affSColin Finck ofs.QuadPart = 0;
706c2c66affSColin Finck hr = IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur );
707c2c66affSColin Finck if (FAILED( hr ))
708c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
709c2c66affSColin Finck }
710c2c66affSColin Finck else
711c2c66affSColin Finck {
712c2c66affSColin Finck /* read the file into a stream and save the stream in the record */
713c2c66affSColin Finck ret = RECORD_StreamFromFile(szFilename, &stm);
714c2c66affSColin Finck if (ret != ERROR_SUCCESS)
715c2c66affSColin Finck return ret;
716c2c66affSColin Finck
717c2c66affSColin Finck /* if all's good, store it in the record */
718c2c66affSColin Finck MSI_RecordSetStream(rec, iField, stm);
719c2c66affSColin Finck }
720c2c66affSColin Finck
721c2c66affSColin Finck return ERROR_SUCCESS;
722c2c66affSColin Finck }
723c2c66affSColin Finck
MsiRecordSetStreamA(MSIHANDLE hRecord,UINT iField,const char * szFilename)72402f995b2Swinesync UINT WINAPI MsiRecordSetStreamA( MSIHANDLE hRecord, UINT iField, const char *szFilename )
725c2c66affSColin Finck {
72602f995b2Swinesync WCHAR *wstr = NULL;
727c2c66affSColin Finck UINT ret;
728c2c66affSColin Finck
72902f995b2Swinesync TRACE( "%lu, %u, %s\n", hRecord, iField, debugstr_a(szFilename) );
730c2c66affSColin Finck
731c2c66affSColin Finck if( szFilename )
732c2c66affSColin Finck {
733c2c66affSColin Finck wstr = strdupAtoW( szFilename );
734c2c66affSColin Finck if( !wstr )
735c2c66affSColin Finck return ERROR_OUTOFMEMORY;
736c2c66affSColin Finck }
737c2c66affSColin Finck ret = MsiRecordSetStreamW(hRecord, iField, wstr);
738*f4be6dc3SMikhail free(wstr);
739c2c66affSColin Finck
740c2c66affSColin Finck return ret;
741c2c66affSColin Finck }
742c2c66affSColin Finck
MsiRecordSetStreamW(MSIHANDLE handle,UINT iField,const WCHAR * szFilename)74302f995b2Swinesync UINT WINAPI MsiRecordSetStreamW( MSIHANDLE handle, UINT iField, const WCHAR *szFilename )
744c2c66affSColin Finck {
745c2c66affSColin Finck MSIRECORD *rec;
746c2c66affSColin Finck UINT ret;
747c2c66affSColin Finck
74802f995b2Swinesync TRACE( "%lu, %u, %s\n", handle, iField, debugstr_w(szFilename) );
749c2c66affSColin Finck
750c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
751c2c66affSColin Finck if( !rec )
752c2c66affSColin Finck return ERROR_INVALID_HANDLE;
753c2c66affSColin Finck
754c2c66affSColin Finck msiobj_lock( &rec->hdr );
755c2c66affSColin Finck ret = MSI_RecordSetStreamFromFileW( rec, iField, szFilename );
756c2c66affSColin Finck msiobj_unlock( &rec->hdr );
757c2c66affSColin Finck msiobj_release( &rec->hdr );
758c2c66affSColin Finck return ret;
759c2c66affSColin Finck }
760c2c66affSColin Finck
MSI_RecordReadStream(MSIRECORD * rec,UINT iField,char * buf,LPDWORD sz)761c2c66affSColin Finck UINT MSI_RecordReadStream(MSIRECORD *rec, UINT iField, char *buf, LPDWORD sz)
762c2c66affSColin Finck {
763c2c66affSColin Finck ULONG count;
764c2c66affSColin Finck HRESULT r;
765c2c66affSColin Finck IStream *stm;
766c2c66affSColin Finck
767c2c66affSColin Finck TRACE("%p %d %p %p\n", rec, iField, buf, sz);
768c2c66affSColin Finck
769c2c66affSColin Finck if( !sz )
770c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
771c2c66affSColin Finck
772c2c66affSColin Finck if( iField > rec->count)
773c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
774c2c66affSColin Finck
775c2c66affSColin Finck if ( rec->fields[iField].type == MSIFIELD_NULL )
776c2c66affSColin Finck {
777c2c66affSColin Finck *sz = 0;
778c2c66affSColin Finck return ERROR_INVALID_DATA;
779c2c66affSColin Finck }
780c2c66affSColin Finck
781c2c66affSColin Finck if( rec->fields[iField].type != MSIFIELD_STREAM )
782c2c66affSColin Finck return ERROR_INVALID_DATATYPE;
783c2c66affSColin Finck
784c2c66affSColin Finck stm = rec->fields[iField].u.stream;
785c2c66affSColin Finck if( !stm )
786c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
787c2c66affSColin Finck
788c2c66affSColin Finck /* if there's no buffer pointer, calculate the length to the end */
789c2c66affSColin Finck if( !buf )
790c2c66affSColin Finck {
791c2c66affSColin Finck LARGE_INTEGER ofs;
792c2c66affSColin Finck ULARGE_INTEGER end, cur;
793c2c66affSColin Finck
794c2c66affSColin Finck ofs.QuadPart = cur.QuadPart = 0;
795c2c66affSColin Finck end.QuadPart = 0;
796c2c66affSColin Finck IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur );
797c2c66affSColin Finck IStream_Seek( stm, ofs, STREAM_SEEK_END, &end );
798c2c66affSColin Finck ofs.QuadPart = cur.QuadPart;
799c2c66affSColin Finck IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur );
800c2c66affSColin Finck *sz = end.QuadPart - cur.QuadPart;
801c2c66affSColin Finck
802c2c66affSColin Finck return ERROR_SUCCESS;
803c2c66affSColin Finck }
804c2c66affSColin Finck
805c2c66affSColin Finck /* read the data */
806c2c66affSColin Finck count = 0;
807c2c66affSColin Finck r = IStream_Read( stm, buf, *sz, &count );
808c2c66affSColin Finck if( FAILED( r ) )
809c2c66affSColin Finck {
810c2c66affSColin Finck *sz = 0;
811c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
812c2c66affSColin Finck }
813c2c66affSColin Finck
814c2c66affSColin Finck *sz = count;
815c2c66affSColin Finck
816c2c66affSColin Finck return ERROR_SUCCESS;
817c2c66affSColin Finck }
818c2c66affSColin Finck
MsiRecordReadStream(MSIHANDLE handle,UINT iField,char * buf,DWORD * sz)81902f995b2Swinesync UINT WINAPI MsiRecordReadStream( MSIHANDLE handle, UINT iField, char *buf, DWORD *sz )
820c2c66affSColin Finck {
821c2c66affSColin Finck MSIRECORD *rec;
822c2c66affSColin Finck UINT ret;
823c2c66affSColin Finck
82402f995b2Swinesync TRACE( "%lu, %u, %p, %p\n", handle, iField, buf, sz );
825c2c66affSColin Finck
826c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
827c2c66affSColin Finck if( !rec )
828c2c66affSColin Finck return ERROR_INVALID_HANDLE;
829c2c66affSColin Finck msiobj_lock( &rec->hdr );
830c2c66affSColin Finck ret = MSI_RecordReadStream( rec, iField, buf, sz );
831c2c66affSColin Finck msiobj_unlock( &rec->hdr );
832c2c66affSColin Finck msiobj_release( &rec->hdr );
833c2c66affSColin Finck return ret;
834c2c66affSColin Finck }
835c2c66affSColin Finck
MSI_RecordSetIStream(MSIRECORD * rec,UINT iField,IStream * stm)836c2c66affSColin Finck UINT MSI_RecordSetIStream( MSIRECORD *rec, UINT iField, IStream *stm )
837c2c66affSColin Finck {
838c2c66affSColin Finck TRACE("%p %d %p\n", rec, iField, stm);
839c2c66affSColin Finck
840c2c66affSColin Finck if( iField > rec->count )
841c2c66affSColin Finck return ERROR_INVALID_FIELD;
842c2c66affSColin Finck
843c2c66affSColin Finck MSI_FreeField( &rec->fields[iField] );
844c2c66affSColin Finck
845c2c66affSColin Finck rec->fields[iField].type = MSIFIELD_STREAM;
846c2c66affSColin Finck rec->fields[iField].u.stream = stm;
847c2c66affSColin Finck IStream_AddRef( stm );
848c2c66affSColin Finck
849c2c66affSColin Finck return ERROR_SUCCESS;
850c2c66affSColin Finck }
851c2c66affSColin Finck
MSI_RecordGetIStream(MSIRECORD * rec,UINT iField,IStream ** pstm)852c2c66affSColin Finck UINT MSI_RecordGetIStream( MSIRECORD *rec, UINT iField, IStream **pstm)
853c2c66affSColin Finck {
854c2c66affSColin Finck TRACE("%p %d %p\n", rec, iField, pstm);
855c2c66affSColin Finck
856c2c66affSColin Finck if( iField > rec->count )
857c2c66affSColin Finck return ERROR_INVALID_FIELD;
858c2c66affSColin Finck
859c2c66affSColin Finck if( rec->fields[iField].type != MSIFIELD_STREAM )
860c2c66affSColin Finck return ERROR_INVALID_FIELD;
861c2c66affSColin Finck
862c2c66affSColin Finck *pstm = rec->fields[iField].u.stream;
863c2c66affSColin Finck IStream_AddRef( *pstm );
864c2c66affSColin Finck
865c2c66affSColin Finck return ERROR_SUCCESS;
866c2c66affSColin Finck }
867c2c66affSColin Finck
dump_stream_to_file(IStream * stm,const WCHAR * name)868*f4be6dc3SMikhail static UINT dump_stream_to_file( IStream *stm, const WCHAR *name )
869c2c66affSColin Finck {
870c2c66affSColin Finck ULARGE_INTEGER size;
871c2c66affSColin Finck LARGE_INTEGER pos;
872c2c66affSColin Finck IStream *out;
873c2c66affSColin Finck DWORD stgm;
874c2c66affSColin Finck HRESULT r;
875c2c66affSColin Finck
876c2c66affSColin Finck stgm = STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE;
877c2c66affSColin Finck r = SHCreateStreamOnFileW( name, stgm, &out );
878c2c66affSColin Finck if( FAILED( r ) )
879c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
880c2c66affSColin Finck
881c2c66affSColin Finck pos.QuadPart = 0;
882c2c66affSColin Finck r = IStream_Seek( stm, pos, STREAM_SEEK_END, &size );
883c2c66affSColin Finck if( FAILED( r ) )
884c2c66affSColin Finck goto end;
885c2c66affSColin Finck
886c2c66affSColin Finck pos.QuadPart = 0;
887c2c66affSColin Finck r = IStream_Seek( stm, pos, STREAM_SEEK_SET, NULL );
888c2c66affSColin Finck if( FAILED( r ) )
889c2c66affSColin Finck goto end;
890c2c66affSColin Finck
891c2c66affSColin Finck r = IStream_CopyTo( stm, out, size, NULL, NULL );
892c2c66affSColin Finck
893c2c66affSColin Finck end:
894c2c66affSColin Finck IStream_Release( out );
895c2c66affSColin Finck if( FAILED( r ) )
896c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
897c2c66affSColin Finck return ERROR_SUCCESS;
898c2c66affSColin Finck }
899c2c66affSColin Finck
MSI_RecordStreamToFile(MSIRECORD * rec,UINT iField,LPCWSTR name)900c2c66affSColin Finck UINT MSI_RecordStreamToFile( MSIRECORD *rec, UINT iField, LPCWSTR name )
901c2c66affSColin Finck {
902c2c66affSColin Finck IStream *stm = NULL;
903c2c66affSColin Finck UINT r;
904c2c66affSColin Finck
905c2c66affSColin Finck TRACE("%p %u %s\n", rec, iField, debugstr_w(name));
906c2c66affSColin Finck
907c2c66affSColin Finck msiobj_lock( &rec->hdr );
908c2c66affSColin Finck
909c2c66affSColin Finck r = MSI_RecordGetIStream( rec, iField, &stm );
910c2c66affSColin Finck if( r == ERROR_SUCCESS )
911c2c66affSColin Finck {
912*f4be6dc3SMikhail r = dump_stream_to_file( stm, name );
913c2c66affSColin Finck IStream_Release( stm );
914c2c66affSColin Finck }
915c2c66affSColin Finck
916c2c66affSColin Finck msiobj_unlock( &rec->hdr );
917c2c66affSColin Finck
918c2c66affSColin Finck return r;
919c2c66affSColin Finck }
920c2c66affSColin Finck
MSI_CloneRecord(MSIRECORD * rec)921c2c66affSColin Finck MSIRECORD *MSI_CloneRecord(MSIRECORD *rec)
922c2c66affSColin Finck {
923c2c66affSColin Finck MSIRECORD *clone;
924c2c66affSColin Finck UINT r, i, count;
925c2c66affSColin Finck
926c2c66affSColin Finck count = MSI_RecordGetFieldCount(rec);
927c2c66affSColin Finck clone = MSI_CreateRecord(count);
928c2c66affSColin Finck if (!clone)
929c2c66affSColin Finck return NULL;
930c2c66affSColin Finck
931c2c66affSColin Finck for (i = 0; i <= count; i++)
932c2c66affSColin Finck {
933c2c66affSColin Finck if (rec->fields[i].type == MSIFIELD_STREAM)
934c2c66affSColin Finck {
935c2c66affSColin Finck if (FAILED(IStream_Clone(rec->fields[i].u.stream,
936c2c66affSColin Finck &clone->fields[i].u.stream)))
937c2c66affSColin Finck {
938c2c66affSColin Finck msiobj_release(&clone->hdr);
939c2c66affSColin Finck return NULL;
940c2c66affSColin Finck }
941c2c66affSColin Finck clone->fields[i].type = MSIFIELD_STREAM;
942c2c66affSColin Finck }
943c2c66affSColin Finck else
944c2c66affSColin Finck {
945c2c66affSColin Finck r = MSI_RecordCopyField(rec, i, clone, i);
946c2c66affSColin Finck if (r != ERROR_SUCCESS)
947c2c66affSColin Finck {
948c2c66affSColin Finck msiobj_release(&clone->hdr);
949c2c66affSColin Finck return NULL;
950c2c66affSColin Finck }
951c2c66affSColin Finck }
952c2c66affSColin Finck }
953c2c66affSColin Finck
954c2c66affSColin Finck return clone;
955c2c66affSColin Finck }
956c2c66affSColin Finck
MSI_RecordsAreFieldsEqual(MSIRECORD * a,MSIRECORD * b,UINT field)957c2c66affSColin Finck BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field)
958c2c66affSColin Finck {
959c2c66affSColin Finck if (a->fields[field].type != b->fields[field].type)
960c2c66affSColin Finck return FALSE;
961c2c66affSColin Finck
962c2c66affSColin Finck switch (a->fields[field].type)
963c2c66affSColin Finck {
964c2c66affSColin Finck case MSIFIELD_NULL:
965c2c66affSColin Finck break;
966c2c66affSColin Finck
967c2c66affSColin Finck case MSIFIELD_INT:
968c2c66affSColin Finck if (a->fields[field].u.iVal != b->fields[field].u.iVal)
969c2c66affSColin Finck return FALSE;
970c2c66affSColin Finck break;
971c2c66affSColin Finck
972c2c66affSColin Finck case MSIFIELD_WSTR:
973c2c66affSColin Finck if (a->fields[field].len != b->fields[field].len) return FALSE;
974c2c66affSColin Finck if (memcmp( a->fields[field].u.szwVal, b->fields[field].u.szwVal,
975c2c66affSColin Finck a->fields[field].len * sizeof(WCHAR) )) return FALSE;
976c2c66affSColin Finck break;
977c2c66affSColin Finck
978c2c66affSColin Finck case MSIFIELD_STREAM:
979c2c66affSColin Finck default:
980c2c66affSColin Finck return FALSE;
981c2c66affSColin Finck }
982c2c66affSColin Finck return TRUE;
983c2c66affSColin Finck }
984c2c66affSColin Finck
985c2c66affSColin Finck
MSI_RecordsAreEqual(MSIRECORD * a,MSIRECORD * b)986c2c66affSColin Finck BOOL MSI_RecordsAreEqual(MSIRECORD *a, MSIRECORD *b)
987c2c66affSColin Finck {
988c2c66affSColin Finck UINT i;
989c2c66affSColin Finck
990c2c66affSColin Finck if (a->count != b->count)
991c2c66affSColin Finck return FALSE;
992c2c66affSColin Finck
993c2c66affSColin Finck for (i = 0; i <= a->count; i++)
994c2c66affSColin Finck {
995c2c66affSColin Finck if (!MSI_RecordsAreFieldsEqual( a, b, i ))
996c2c66affSColin Finck return FALSE;
997c2c66affSColin Finck }
998c2c66affSColin Finck
999c2c66affSColin Finck return TRUE;
1000c2c66affSColin Finck }
1001c2c66affSColin Finck
msi_dup_record_field(MSIRECORD * rec,INT field)1002c2c66affSColin Finck WCHAR *msi_dup_record_field( MSIRECORD *rec, INT field )
1003c2c66affSColin Finck {
1004c2c66affSColin Finck DWORD sz = 0;
1005c2c66affSColin Finck WCHAR *str;
1006c2c66affSColin Finck UINT r;
1007c2c66affSColin Finck
1008c2c66affSColin Finck if (MSI_RecordIsNull( rec, field )) return NULL;
1009c2c66affSColin Finck
1010c2c66affSColin Finck r = MSI_RecordGetStringW( rec, field, NULL, &sz );
1011c2c66affSColin Finck if (r != ERROR_SUCCESS)
1012c2c66affSColin Finck return NULL;
1013c2c66affSColin Finck
1014c2c66affSColin Finck sz++;
1015*f4be6dc3SMikhail str = malloc( sz * sizeof(WCHAR) );
1016c2c66affSColin Finck if (!str) return NULL;
1017c2c66affSColin Finck str[0] = 0;
1018c2c66affSColin Finck r = MSI_RecordGetStringW( rec, field, str, &sz );
1019c2c66affSColin Finck if (r != ERROR_SUCCESS)
1020c2c66affSColin Finck {
1021c2c66affSColin Finck ERR("failed to get string!\n");
1022*f4be6dc3SMikhail free( str );
1023c2c66affSColin Finck return NULL;
1024c2c66affSColin Finck }
1025c2c66affSColin Finck return str;
1026c2c66affSColin Finck }
102771bffdcdSAmine Khaldi
dump_record(MSIRECORD * rec)102871bffdcdSAmine Khaldi void dump_record(MSIRECORD *rec)
102971bffdcdSAmine Khaldi {
103071bffdcdSAmine Khaldi int i;
103171bffdcdSAmine Khaldi if (!rec)
103271bffdcdSAmine Khaldi {
103371bffdcdSAmine Khaldi TRACE("(null)\n");
103471bffdcdSAmine Khaldi return;
103571bffdcdSAmine Khaldi }
103671bffdcdSAmine Khaldi
103771bffdcdSAmine Khaldi TRACE("[");
103871bffdcdSAmine Khaldi for (i = 0; i <= rec->count; i++)
103971bffdcdSAmine Khaldi {
104071bffdcdSAmine Khaldi switch(rec->fields[i].type)
104171bffdcdSAmine Khaldi {
104271bffdcdSAmine Khaldi case MSIFIELD_NULL: TRACE("(null)"); break;
104371bffdcdSAmine Khaldi case MSIFIELD_INT: TRACE("%d", rec->fields[i].u.iVal); break;
104471bffdcdSAmine Khaldi case MSIFIELD_WSTR: TRACE("%s", debugstr_w(rec->fields[i].u.szwVal)); break;
104571bffdcdSAmine Khaldi case MSIFIELD_STREAM: TRACE("%p", rec->fields[i].u.stream); break;
104671bffdcdSAmine Khaldi }
104771bffdcdSAmine Khaldi if (i < rec->count) TRACE(", ");
104871bffdcdSAmine Khaldi }
104971bffdcdSAmine Khaldi TRACE("]\n");
105071bffdcdSAmine Khaldi }
10512e19edd6Swinesync
copy_remote_record(const struct wire_record * in,MSIHANDLE out)1052aede536cSwinesync UINT copy_remote_record(const struct wire_record *in, MSIHANDLE out)
10532e19edd6Swinesync {
10542e19edd6Swinesync MSIRECORD *rec;
10552e19edd6Swinesync unsigned int i;
10568c04add1Swinesync UINT r = ERROR_SUCCESS;
10572e19edd6Swinesync
1058aede536cSwinesync if (!(rec = msihandle2msiinfo(out, MSIHANDLETYPE_RECORD)))
1059aede536cSwinesync return ERROR_INVALID_HANDLE;
10602e19edd6Swinesync
106114478462Swinesync rec->cookie = in->cookie;
10622e19edd6Swinesync for (i = 0; i <= in->count; i++)
10632e19edd6Swinesync {
10642e19edd6Swinesync switch (in->fields[i].type)
10652e19edd6Swinesync {
10662e19edd6Swinesync case MSIFIELD_NULL:
1067aede536cSwinesync MSI_FreeField(&rec->fields[i]);
1068aede536cSwinesync rec->fields[i].type = MSIFIELD_NULL;
10692e19edd6Swinesync break;
10702e19edd6Swinesync case MSIFIELD_INT:
10712e19edd6Swinesync r = MSI_RecordSetInteger(rec, i, in->fields[i].u.iVal);
10722e19edd6Swinesync break;
10732e19edd6Swinesync case MSIFIELD_WSTR:
10742e19edd6Swinesync r = MSI_RecordSetStringW(rec, i, in->fields[i].u.szwVal);
10752e19edd6Swinesync break;
10762e19edd6Swinesync case MSIFIELD_STREAM:
10772e19edd6Swinesync r = MSI_RecordSetIStream(rec, i, in->fields[i].u.stream);
10782e19edd6Swinesync break;
10792e19edd6Swinesync default:
10802e19edd6Swinesync ERR("invalid field type %d\n", in->fields[i].type);
10812e19edd6Swinesync break;
10822e19edd6Swinesync }
10832e19edd6Swinesync
10842e19edd6Swinesync if (r)
10852e19edd6Swinesync {
10862e19edd6Swinesync msiobj_release(&rec->hdr);
10872e19edd6Swinesync return r;
10882e19edd6Swinesync }
10892e19edd6Swinesync }
10902e19edd6Swinesync
10912e19edd6Swinesync msiobj_release(&rec->hdr);
10922e19edd6Swinesync return ERROR_SUCCESS;
10932e19edd6Swinesync }
1094795da528Swinesync
unmarshal_record(const struct wire_record * in,MSIHANDLE * out)1095aede536cSwinesync UINT unmarshal_record(const struct wire_record *in, MSIHANDLE *out)
1096aede536cSwinesync {
1097aede536cSwinesync if (!in)
1098aede536cSwinesync {
1099aede536cSwinesync *out = 0;
1100aede536cSwinesync return ERROR_SUCCESS;
1101aede536cSwinesync }
1102aede536cSwinesync
1103aede536cSwinesync *out = MsiCreateRecord(in->count);
1104aede536cSwinesync if (!*out) return ERROR_OUTOFMEMORY;
1105aede536cSwinesync
1106aede536cSwinesync return copy_remote_record(in, *out);
1107aede536cSwinesync }
1108aede536cSwinesync
marshal_record(MSIHANDLE handle)1109795da528Swinesync struct wire_record *marshal_record(MSIHANDLE handle)
1110795da528Swinesync {
1111795da528Swinesync struct wire_record *ret;
111214478462Swinesync unsigned int i;
1113795da528Swinesync MSIRECORD *rec;
1114795da528Swinesync
1115795da528Swinesync if (!(rec = msihandle2msiinfo(handle, MSIHANDLETYPE_RECORD)))
1116795da528Swinesync return NULL;
1117795da528Swinesync
111814478462Swinesync ret = midl_user_allocate(sizeof(*ret) + rec->count * sizeof(ret->fields[0]));
111914478462Swinesync ret->count = rec->count;
112014478462Swinesync ret->cookie = rec->cookie;
1121795da528Swinesync
112214478462Swinesync for (i = 0; i <= rec->count; i++)
1123795da528Swinesync {
1124795da528Swinesync switch (rec->fields[i].type)
1125795da528Swinesync {
1126795da528Swinesync case MSIFIELD_NULL:
1127795da528Swinesync break;
1128795da528Swinesync case MSIFIELD_INT:
1129795da528Swinesync ret->fields[i].u.iVal = rec->fields[i].u.iVal;
1130795da528Swinesync break;
1131795da528Swinesync case MSIFIELD_WSTR:
1132*f4be6dc3SMikhail ret->fields[i].u.szwVal = wcsdup(rec->fields[i].u.szwVal);
1133795da528Swinesync break;
1134795da528Swinesync case MSIFIELD_STREAM:
1135795da528Swinesync IStream_AddRef(rec->fields[i].u.stream);
1136795da528Swinesync ret->fields[i].u.stream = rec->fields[i].u.stream;
1137795da528Swinesync break;
1138795da528Swinesync default:
1139795da528Swinesync ERR("invalid field type %d\n", rec->fields[i].type);
1140795da528Swinesync break;
1141795da528Swinesync }
1142795da528Swinesync ret->fields[i].type = rec->fields[i].type;
1143795da528Swinesync }
1144795da528Swinesync
1145795da528Swinesync msiobj_release(&rec->hdr);
1146795da528Swinesync return ret;
1147795da528Swinesync }
1148795da528Swinesync
free_remote_record(struct wire_record * rec)1149795da528Swinesync void free_remote_record(struct wire_record *rec)
1150795da528Swinesync {
1151795da528Swinesync int i;
1152795da528Swinesync
1153795da528Swinesync for (i = 0; i <= rec->count; i++)
1154795da528Swinesync {
1155795da528Swinesync if (rec->fields[i].type == MSIFIELD_WSTR)
1156795da528Swinesync midl_user_free(rec->fields[i].u.szwVal);
1157795da528Swinesync else if (rec->fields[i].type == MSIFIELD_STREAM)
1158795da528Swinesync IStream_Release(rec->fields[i].u.stream);
1159795da528Swinesync }
1160795da528Swinesync
1161795da528Swinesync midl_user_free(rec);
1162795da528Swinesync }
1163