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 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: 57c2c66affSColin Finck msi_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 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 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 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 108c2c66affSColin Finck UINT MSI_RecordGetFieldCount( const MSIRECORD *rec ) 109c2c66affSColin Finck { 110c2c66affSColin Finck return rec->count; 111c2c66affSColin Finck } 112c2c66affSColin Finck 113c2c66affSColin Finck UINT WINAPI MsiRecordGetFieldCount( MSIHANDLE handle ) 114c2c66affSColin Finck { 115c2c66affSColin Finck MSIRECORD *rec; 116c2c66affSColin Finck UINT ret; 117c2c66affSColin Finck 118c2c66affSColin Finck TRACE("%d\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 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 155c2c66affSColin Finck WCHAR *msi_strdupW( const WCHAR *value, int len ) 156c2c66affSColin Finck { 157c2c66affSColin Finck WCHAR *ret; 158c2c66affSColin Finck 159c2c66affSColin Finck if (!value) return NULL; 160c2c66affSColin Finck if (!(ret = msi_alloc( (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 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 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 237c2c66affSColin Finck int WINAPI MsiRecordGetInteger( MSIHANDLE handle, UINT iField) 238c2c66affSColin Finck { 239c2c66affSColin Finck MSIRECORD *rec; 240c2c66affSColin Finck UINT ret; 241c2c66affSColin Finck 242c2c66affSColin Finck TRACE("%d %d\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 256c2c66affSColin Finck UINT WINAPI MsiRecordClearData( MSIHANDLE handle ) 257c2c66affSColin Finck { 258c2c66affSColin Finck MSIRECORD *rec; 259c2c66affSColin Finck UINT i; 260c2c66affSColin Finck 261c2c66affSColin Finck TRACE("%d\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 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 303c2c66affSColin Finck UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, UINT iField, int iVal ) 304c2c66affSColin Finck { 305c2c66affSColin Finck MSIRECORD *rec; 306c2c66affSColin Finck UINT ret; 307c2c66affSColin Finck 308c2c66affSColin Finck TRACE("%d %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 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 333c2c66affSColin Finck BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, UINT iField ) 334c2c66affSColin Finck { 335c2c66affSColin Finck MSIRECORD *rec; 336c2c66affSColin Finck UINT ret; 337c2c66affSColin Finck 338c2c66affSColin Finck TRACE("%d %d\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 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 403c2c66affSColin Finck UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, UINT iField, 404c2c66affSColin Finck LPSTR szValue, LPDWORD pcchValue) 405c2c66affSColin Finck { 406c2c66affSColin Finck MSIRECORD *rec; 407c2c66affSColin Finck UINT ret; 408c2c66affSColin Finck 409c2c66affSColin Finck TRACE("%d %d %p %p\n", handle, iField, szValue, pcchValue); 410c2c66affSColin Finck 411c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); 412c2c66affSColin Finck if( !rec ) 413c2c66affSColin Finck return ERROR_INVALID_HANDLE; 414c2c66affSColin Finck msiobj_lock( &rec->hdr ); 415c2c66affSColin Finck ret = MSI_RecordGetStringA( rec, iField, szValue, pcchValue); 416c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 417c2c66affSColin Finck msiobj_release( &rec->hdr ); 418c2c66affSColin Finck return ret; 419c2c66affSColin Finck } 420c2c66affSColin Finck 421c2c66affSColin Finck const WCHAR *msi_record_get_string( const MSIRECORD *rec, UINT field, int *len ) 422c2c66affSColin Finck { 423c2c66affSColin Finck if (field > rec->count) 424c2c66affSColin Finck return NULL; 425c2c66affSColin Finck 426c2c66affSColin Finck if (rec->fields[field].type != MSIFIELD_WSTR) 427c2c66affSColin Finck return NULL; 428c2c66affSColin Finck 429c2c66affSColin Finck if (len) *len = rec->fields[field].len; 430c2c66affSColin Finck 431c2c66affSColin Finck return rec->fields[field].u.szwVal; 432c2c66affSColin Finck } 433c2c66affSColin Finck 434c2c66affSColin Finck const WCHAR *MSI_RecordGetString( const MSIRECORD *rec, UINT iField ) 435c2c66affSColin Finck { 436c2c66affSColin Finck return msi_record_get_string( rec, iField, NULL ); 437c2c66affSColin Finck } 438c2c66affSColin Finck 439c2c66affSColin Finck UINT MSI_RecordGetStringW(MSIRECORD *rec, UINT iField, 440c2c66affSColin Finck LPWSTR szValue, LPDWORD pcchValue) 441c2c66affSColin Finck { 442c2c66affSColin Finck UINT len = 0, ret = ERROR_SUCCESS; 443c2c66affSColin Finck WCHAR buffer[16]; 444c2c66affSColin Finck 445c2c66affSColin Finck TRACE("%p %d %p %p\n", rec, iField, szValue, pcchValue); 446c2c66affSColin Finck 447c2c66affSColin Finck if( iField > rec->count ) 448c2c66affSColin Finck { 449c2c66affSColin Finck if ( szValue && *pcchValue > 0 ) 450c2c66affSColin Finck szValue[0] = 0; 451c2c66affSColin Finck 452c2c66affSColin Finck *pcchValue = 0; 453c2c66affSColin Finck return ERROR_SUCCESS; 454c2c66affSColin Finck } 455c2c66affSColin Finck 456c2c66affSColin Finck switch( rec->fields[iField].type ) 457c2c66affSColin Finck { 458c2c66affSColin Finck case MSIFIELD_INT: 459*74f53b4bSwinesync wsprintfW(buffer, L"%d", rec->fields[iField].u.iVal); 460c2c66affSColin Finck len = lstrlenW( buffer ); 461c2c66affSColin Finck if (szValue) 462c2c66affSColin Finck lstrcpynW(szValue, buffer, *pcchValue); 463c2c66affSColin Finck break; 464c2c66affSColin Finck case MSIFIELD_WSTR: 465c2c66affSColin Finck len = rec->fields[iField].len; 466c2c66affSColin Finck if (szValue) 467c2c66affSColin Finck memcpy( szValue, rec->fields[iField].u.szwVal, min(len + 1, *pcchValue) * sizeof(WCHAR) ); 468c2c66affSColin Finck break; 469c2c66affSColin Finck case MSIFIELD_NULL: 470c2c66affSColin Finck if( szValue && *pcchValue > 0 ) 471c2c66affSColin Finck szValue[0] = 0; 472c2c66affSColin Finck break; 473c2c66affSColin Finck default: 474c2c66affSColin Finck break; 475c2c66affSColin Finck } 476c2c66affSColin Finck 477c2c66affSColin Finck if( szValue && *pcchValue <= len ) 478c2c66affSColin Finck ret = ERROR_MORE_DATA; 479c2c66affSColin Finck *pcchValue = len; 480c2c66affSColin Finck 481c2c66affSColin Finck return ret; 482c2c66affSColin Finck } 483c2c66affSColin Finck 484c2c66affSColin Finck UINT WINAPI MsiRecordGetStringW(MSIHANDLE handle, UINT iField, 485c2c66affSColin Finck LPWSTR szValue, LPDWORD pcchValue) 486c2c66affSColin Finck { 487c2c66affSColin Finck MSIRECORD *rec; 488c2c66affSColin Finck UINT ret; 489c2c66affSColin Finck 490c2c66affSColin Finck TRACE("%d %d %p %p\n", handle, iField, szValue, pcchValue); 491c2c66affSColin Finck 492c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); 493c2c66affSColin Finck if( !rec ) 494c2c66affSColin Finck return ERROR_INVALID_HANDLE; 495c2c66affSColin Finck 496c2c66affSColin Finck msiobj_lock( &rec->hdr ); 497c2c66affSColin Finck ret = MSI_RecordGetStringW( rec, iField, szValue, pcchValue ); 498c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 499c2c66affSColin Finck msiobj_release( &rec->hdr ); 500c2c66affSColin Finck return ret; 501c2c66affSColin Finck } 502c2c66affSColin Finck 503c2c66affSColin Finck static UINT msi_get_stream_size( IStream *stm ) 504c2c66affSColin Finck { 505c2c66affSColin Finck STATSTG stat; 506c2c66affSColin Finck HRESULT r; 507c2c66affSColin Finck 508c2c66affSColin Finck r = IStream_Stat( stm, &stat, STATFLAG_NONAME ); 509c2c66affSColin Finck if( FAILED(r) ) 510c2c66affSColin Finck return 0; 511c2c66affSColin Finck return stat.cbSize.QuadPart; 512c2c66affSColin Finck } 513c2c66affSColin Finck 514c2c66affSColin Finck static UINT MSI_RecordDataSize(MSIRECORD *rec, UINT iField) 515c2c66affSColin Finck { 516c2c66affSColin Finck TRACE("%p %d\n", rec, iField); 517c2c66affSColin Finck 518c2c66affSColin Finck if( iField > rec->count ) 519c2c66affSColin Finck return 0; 520c2c66affSColin Finck 521c2c66affSColin Finck switch( rec->fields[iField].type ) 522c2c66affSColin Finck { 523c2c66affSColin Finck case MSIFIELD_INT: 524c2c66affSColin Finck return sizeof (INT); 525c2c66affSColin Finck case MSIFIELD_WSTR: 526c2c66affSColin Finck return rec->fields[iField].len; 527c2c66affSColin Finck case MSIFIELD_NULL: 528c2c66affSColin Finck break; 529c2c66affSColin Finck case MSIFIELD_STREAM: 530c2c66affSColin Finck return msi_get_stream_size( rec->fields[iField].u.stream ); 531c2c66affSColin Finck } 532c2c66affSColin Finck return 0; 533c2c66affSColin Finck } 534c2c66affSColin Finck 535c2c66affSColin Finck UINT WINAPI MsiRecordDataSize(MSIHANDLE handle, UINT iField) 536c2c66affSColin Finck { 537c2c66affSColin Finck MSIRECORD *rec; 538c2c66affSColin Finck UINT ret; 539c2c66affSColin Finck 540c2c66affSColin Finck TRACE("%d %d\n", handle, iField); 541c2c66affSColin Finck 542c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); 543c2c66affSColin Finck if( !rec ) 544c2c66affSColin Finck return 0; 545c2c66affSColin Finck msiobj_lock( &rec->hdr ); 546c2c66affSColin Finck ret = MSI_RecordDataSize( rec, iField); 547c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 548c2c66affSColin Finck msiobj_release( &rec->hdr ); 549c2c66affSColin Finck return ret; 550c2c66affSColin Finck } 551c2c66affSColin Finck 552c2c66affSColin Finck UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, UINT iField, LPCSTR szValue ) 553c2c66affSColin Finck { 554c2c66affSColin Finck WCHAR *valueW = NULL; 555c2c66affSColin Finck MSIRECORD *rec; 556c2c66affSColin Finck UINT ret; 557c2c66affSColin Finck 558c2c66affSColin Finck TRACE("%d %d %s\n", handle, iField, debugstr_a(szValue)); 559c2c66affSColin Finck 560c2c66affSColin Finck if (szValue && !(valueW = strdupAtoW( szValue ))) return ERROR_OUTOFMEMORY; 561c2c66affSColin Finck 562c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); 563c2c66affSColin Finck if( !rec ) 564c2c66affSColin Finck { 565c2c66affSColin Finck msi_free( valueW ); 566c2c66affSColin Finck return ERROR_INVALID_HANDLE; 567c2c66affSColin Finck } 568c2c66affSColin Finck msiobj_lock( &rec->hdr ); 569c2c66affSColin Finck ret = MSI_RecordSetStringW( rec, iField, valueW ); 570c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 571c2c66affSColin Finck msiobj_release( &rec->hdr ); 572c2c66affSColin Finck msi_free( valueW ); 573c2c66affSColin Finck return ret; 574c2c66affSColin Finck } 575c2c66affSColin Finck 576c2c66affSColin Finck UINT msi_record_set_string( MSIRECORD *rec, UINT field, const WCHAR *value, int len ) 577c2c66affSColin Finck { 578c2c66affSColin Finck if (field > rec->count) 579c2c66affSColin Finck return ERROR_INVALID_FIELD; 580c2c66affSColin Finck 581c2c66affSColin Finck MSI_FreeField( &rec->fields[field] ); 582c2c66affSColin Finck 583958f1addSwinesync if (value && len < 0) len = lstrlenW( value ); 584c2c66affSColin Finck 585c2c66affSColin Finck if (value && len) 586c2c66affSColin Finck { 587c2c66affSColin Finck rec->fields[field].type = MSIFIELD_WSTR; 588c2c66affSColin Finck rec->fields[field].u.szwVal = msi_strdupW( value, len ); 589c2c66affSColin Finck rec->fields[field].len = len; 590c2c66affSColin Finck } 591c2c66affSColin Finck else 592c2c66affSColin Finck { 593c2c66affSColin Finck rec->fields[field].type = MSIFIELD_NULL; 594c2c66affSColin Finck rec->fields[field].u.szwVal = NULL; 595c2c66affSColin Finck rec->fields[field].len = 0; 596c2c66affSColin Finck } 597c2c66affSColin Finck return 0; 598c2c66affSColin Finck } 599c2c66affSColin Finck 600c2c66affSColin Finck UINT MSI_RecordSetStringW( MSIRECORD *rec, UINT iField, LPCWSTR szValue ) 601c2c66affSColin Finck { 602c2c66affSColin Finck TRACE("%p %d %s\n", rec, iField, debugstr_w(szValue)); 603c2c66affSColin Finck 604c2c66affSColin Finck return msi_record_set_string( rec, iField, szValue, -1 ); 605c2c66affSColin Finck } 606c2c66affSColin Finck 607c2c66affSColin Finck UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, UINT iField, LPCWSTR szValue ) 608c2c66affSColin Finck { 609c2c66affSColin Finck MSIRECORD *rec; 610c2c66affSColin Finck UINT ret; 611c2c66affSColin Finck 612c2c66affSColin Finck TRACE("%d %d %s\n", handle, iField, debugstr_w(szValue)); 613c2c66affSColin Finck 614c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); 615c2c66affSColin Finck if( !rec ) 616c2c66affSColin Finck return ERROR_INVALID_HANDLE; 617c2c66affSColin Finck 618c2c66affSColin Finck msiobj_lock( &rec->hdr ); 619c2c66affSColin Finck ret = MSI_RecordSetStringW( rec, iField, szValue ); 620c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 621c2c66affSColin Finck msiobj_release( &rec->hdr ); 622c2c66affSColin Finck return ret; 623c2c66affSColin Finck } 624c2c66affSColin Finck 625c2c66affSColin Finck /* read the data in a file into an IStream */ 626c2c66affSColin Finck static UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm) 627c2c66affSColin Finck { 628c2c66affSColin Finck DWORD sz, szHighWord = 0, read; 629c2c66affSColin Finck HANDLE handle; 630c2c66affSColin Finck HGLOBAL hGlob = 0; 631c2c66affSColin Finck HRESULT hr; 632c2c66affSColin Finck ULARGE_INTEGER ulSize; 633c2c66affSColin Finck 634c2c66affSColin Finck TRACE("reading %s\n", debugstr_w(szFile)); 635c2c66affSColin Finck 636c2c66affSColin Finck /* read the file into memory */ 637c2c66affSColin Finck handle = CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 638c2c66affSColin Finck if( handle == INVALID_HANDLE_VALUE ) 639c2c66affSColin Finck return GetLastError(); 640c2c66affSColin Finck sz = GetFileSize(handle, &szHighWord); 641c2c66affSColin Finck if( sz != INVALID_FILE_SIZE && szHighWord == 0 ) 642c2c66affSColin Finck { 643c2c66affSColin Finck hGlob = GlobalAlloc(GMEM_FIXED, sz); 644c2c66affSColin Finck if( hGlob ) 645c2c66affSColin Finck { 646c2c66affSColin Finck BOOL r = ReadFile(handle, hGlob, sz, &read, NULL) && read == sz; 647c2c66affSColin Finck if( !r ) 648c2c66affSColin Finck { 649c2c66affSColin Finck GlobalFree(hGlob); 650c2c66affSColin Finck hGlob = 0; 651c2c66affSColin Finck } 652c2c66affSColin Finck } 653c2c66affSColin Finck } 654c2c66affSColin Finck CloseHandle(handle); 655c2c66affSColin Finck if( !hGlob ) 656c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 657c2c66affSColin Finck 658c2c66affSColin Finck /* make a stream out of it, and set the correct file size */ 659c2c66affSColin Finck hr = CreateStreamOnHGlobal(hGlob, TRUE, pstm); 660c2c66affSColin Finck if( FAILED( hr ) ) 661c2c66affSColin Finck { 662c2c66affSColin Finck GlobalFree(hGlob); 663c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 664c2c66affSColin Finck } 665c2c66affSColin Finck 666c2c66affSColin Finck /* set the correct size - CreateStreamOnHGlobal screws it up */ 667c2c66affSColin Finck ulSize.QuadPart = sz; 668c2c66affSColin Finck IStream_SetSize(*pstm, ulSize); 669c2c66affSColin Finck 670c2c66affSColin Finck TRACE("read %s, %d bytes into IStream %p\n", debugstr_w(szFile), sz, *pstm); 671c2c66affSColin Finck 672c2c66affSColin Finck return ERROR_SUCCESS; 673c2c66affSColin Finck } 674c2c66affSColin Finck 675c2c66affSColin Finck UINT MSI_RecordSetStream(MSIRECORD *rec, UINT iField, IStream *stream) 676c2c66affSColin Finck { 677c2c66affSColin Finck if ( (iField == 0) || (iField > rec->count) ) 678c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 679c2c66affSColin Finck 680c2c66affSColin Finck MSI_FreeField( &rec->fields[iField] ); 681c2c66affSColin Finck rec->fields[iField].type = MSIFIELD_STREAM; 682c2c66affSColin Finck rec->fields[iField].u.stream = stream; 683c2c66affSColin Finck 684c2c66affSColin Finck return ERROR_SUCCESS; 685c2c66affSColin Finck } 686c2c66affSColin Finck 687c2c66affSColin Finck UINT MSI_RecordSetStreamFromFileW(MSIRECORD *rec, UINT iField, LPCWSTR szFilename) 688c2c66affSColin Finck { 689c2c66affSColin Finck IStream *stm = NULL; 690c2c66affSColin Finck HRESULT hr; 691c2c66affSColin Finck UINT ret; 692c2c66affSColin Finck 693c2c66affSColin Finck if( (iField == 0) || (iField > rec->count) ) 694c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 695c2c66affSColin Finck 696c2c66affSColin Finck /* no filename means we should seek back to the start of the stream */ 697c2c66affSColin Finck if( !szFilename ) 698c2c66affSColin Finck { 699c2c66affSColin Finck LARGE_INTEGER ofs; 700c2c66affSColin Finck ULARGE_INTEGER cur; 701c2c66affSColin Finck 702c2c66affSColin Finck if( rec->fields[iField].type != MSIFIELD_STREAM ) 703c2c66affSColin Finck return ERROR_INVALID_FIELD; 704c2c66affSColin Finck 705c2c66affSColin Finck stm = rec->fields[iField].u.stream; 706c2c66affSColin Finck if( !stm ) 707c2c66affSColin Finck return ERROR_INVALID_FIELD; 708c2c66affSColin Finck 709c2c66affSColin Finck ofs.QuadPart = 0; 710c2c66affSColin Finck hr = IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur ); 711c2c66affSColin Finck if (FAILED( hr )) 712c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 713c2c66affSColin Finck } 714c2c66affSColin Finck else 715c2c66affSColin Finck { 716c2c66affSColin Finck /* read the file into a stream and save the stream in the record */ 717c2c66affSColin Finck ret = RECORD_StreamFromFile(szFilename, &stm); 718c2c66affSColin Finck if (ret != ERROR_SUCCESS) 719c2c66affSColin Finck return ret; 720c2c66affSColin Finck 721c2c66affSColin Finck /* if all's good, store it in the record */ 722c2c66affSColin Finck MSI_RecordSetStream(rec, iField, stm); 723c2c66affSColin Finck } 724c2c66affSColin Finck 725c2c66affSColin Finck return ERROR_SUCCESS; 726c2c66affSColin Finck } 727c2c66affSColin Finck 728c2c66affSColin Finck UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, UINT iField, LPCSTR szFilename) 729c2c66affSColin Finck { 730c2c66affSColin Finck LPWSTR wstr = NULL; 731c2c66affSColin Finck UINT ret; 732c2c66affSColin Finck 733c2c66affSColin Finck TRACE("%d %d %s\n", hRecord, iField, debugstr_a(szFilename)); 734c2c66affSColin Finck 735c2c66affSColin Finck if( szFilename ) 736c2c66affSColin Finck { 737c2c66affSColin Finck wstr = strdupAtoW( szFilename ); 738c2c66affSColin Finck if( !wstr ) 739c2c66affSColin Finck return ERROR_OUTOFMEMORY; 740c2c66affSColin Finck } 741c2c66affSColin Finck ret = MsiRecordSetStreamW(hRecord, iField, wstr); 742c2c66affSColin Finck msi_free(wstr); 743c2c66affSColin Finck 744c2c66affSColin Finck return ret; 745c2c66affSColin Finck } 746c2c66affSColin Finck 747c2c66affSColin Finck UINT WINAPI MsiRecordSetStreamW(MSIHANDLE handle, UINT iField, LPCWSTR szFilename) 748c2c66affSColin Finck { 749c2c66affSColin Finck MSIRECORD *rec; 750c2c66affSColin Finck UINT ret; 751c2c66affSColin Finck 752c2c66affSColin Finck TRACE("%d %d %s\n", handle, iField, debugstr_w(szFilename)); 753c2c66affSColin Finck 754c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); 755c2c66affSColin Finck if( !rec ) 756c2c66affSColin Finck return ERROR_INVALID_HANDLE; 757c2c66affSColin Finck 758c2c66affSColin Finck msiobj_lock( &rec->hdr ); 759c2c66affSColin Finck ret = MSI_RecordSetStreamFromFileW( rec, iField, szFilename ); 760c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 761c2c66affSColin Finck msiobj_release( &rec->hdr ); 762c2c66affSColin Finck return ret; 763c2c66affSColin Finck } 764c2c66affSColin Finck 765c2c66affSColin Finck UINT MSI_RecordReadStream(MSIRECORD *rec, UINT iField, char *buf, LPDWORD sz) 766c2c66affSColin Finck { 767c2c66affSColin Finck ULONG count; 768c2c66affSColin Finck HRESULT r; 769c2c66affSColin Finck IStream *stm; 770c2c66affSColin Finck 771c2c66affSColin Finck TRACE("%p %d %p %p\n", rec, iField, buf, sz); 772c2c66affSColin Finck 773c2c66affSColin Finck if( !sz ) 774c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 775c2c66affSColin Finck 776c2c66affSColin Finck if( iField > rec->count) 777c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 778c2c66affSColin Finck 779c2c66affSColin Finck if ( rec->fields[iField].type == MSIFIELD_NULL ) 780c2c66affSColin Finck { 781c2c66affSColin Finck *sz = 0; 782c2c66affSColin Finck return ERROR_INVALID_DATA; 783c2c66affSColin Finck } 784c2c66affSColin Finck 785c2c66affSColin Finck if( rec->fields[iField].type != MSIFIELD_STREAM ) 786c2c66affSColin Finck return ERROR_INVALID_DATATYPE; 787c2c66affSColin Finck 788c2c66affSColin Finck stm = rec->fields[iField].u.stream; 789c2c66affSColin Finck if( !stm ) 790c2c66affSColin Finck return ERROR_INVALID_PARAMETER; 791c2c66affSColin Finck 792c2c66affSColin Finck /* if there's no buffer pointer, calculate the length to the end */ 793c2c66affSColin Finck if( !buf ) 794c2c66affSColin Finck { 795c2c66affSColin Finck LARGE_INTEGER ofs; 796c2c66affSColin Finck ULARGE_INTEGER end, cur; 797c2c66affSColin Finck 798c2c66affSColin Finck ofs.QuadPart = cur.QuadPart = 0; 799c2c66affSColin Finck end.QuadPart = 0; 800c2c66affSColin Finck IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur ); 801c2c66affSColin Finck IStream_Seek( stm, ofs, STREAM_SEEK_END, &end ); 802c2c66affSColin Finck ofs.QuadPart = cur.QuadPart; 803c2c66affSColin Finck IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur ); 804c2c66affSColin Finck *sz = end.QuadPart - cur.QuadPart; 805c2c66affSColin Finck 806c2c66affSColin Finck return ERROR_SUCCESS; 807c2c66affSColin Finck } 808c2c66affSColin Finck 809c2c66affSColin Finck /* read the data */ 810c2c66affSColin Finck count = 0; 811c2c66affSColin Finck r = IStream_Read( stm, buf, *sz, &count ); 812c2c66affSColin Finck if( FAILED( r ) ) 813c2c66affSColin Finck { 814c2c66affSColin Finck *sz = 0; 815c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 816c2c66affSColin Finck } 817c2c66affSColin Finck 818c2c66affSColin Finck *sz = count; 819c2c66affSColin Finck 820c2c66affSColin Finck return ERROR_SUCCESS; 821c2c66affSColin Finck } 822c2c66affSColin Finck 823c2c66affSColin Finck UINT WINAPI MsiRecordReadStream(MSIHANDLE handle, UINT iField, char *buf, LPDWORD sz) 824c2c66affSColin Finck { 825c2c66affSColin Finck MSIRECORD *rec; 826c2c66affSColin Finck UINT ret; 827c2c66affSColin Finck 828c2c66affSColin Finck TRACE("%d %d %p %p\n", handle, iField, buf, sz); 829c2c66affSColin Finck 830c2c66affSColin Finck rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); 831c2c66affSColin Finck if( !rec ) 832c2c66affSColin Finck return ERROR_INVALID_HANDLE; 833c2c66affSColin Finck msiobj_lock( &rec->hdr ); 834c2c66affSColin Finck ret = MSI_RecordReadStream( rec, iField, buf, sz ); 835c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 836c2c66affSColin Finck msiobj_release( &rec->hdr ); 837c2c66affSColin Finck return ret; 838c2c66affSColin Finck } 839c2c66affSColin Finck 840c2c66affSColin Finck UINT MSI_RecordSetIStream( MSIRECORD *rec, UINT iField, IStream *stm ) 841c2c66affSColin Finck { 842c2c66affSColin Finck TRACE("%p %d %p\n", rec, iField, stm); 843c2c66affSColin Finck 844c2c66affSColin Finck if( iField > rec->count ) 845c2c66affSColin Finck return ERROR_INVALID_FIELD; 846c2c66affSColin Finck 847c2c66affSColin Finck MSI_FreeField( &rec->fields[iField] ); 848c2c66affSColin Finck 849c2c66affSColin Finck rec->fields[iField].type = MSIFIELD_STREAM; 850c2c66affSColin Finck rec->fields[iField].u.stream = stm; 851c2c66affSColin Finck IStream_AddRef( stm ); 852c2c66affSColin Finck 853c2c66affSColin Finck return ERROR_SUCCESS; 854c2c66affSColin Finck } 855c2c66affSColin Finck 856c2c66affSColin Finck UINT MSI_RecordGetIStream( MSIRECORD *rec, UINT iField, IStream **pstm) 857c2c66affSColin Finck { 858c2c66affSColin Finck TRACE("%p %d %p\n", rec, iField, pstm); 859c2c66affSColin Finck 860c2c66affSColin Finck if( iField > rec->count ) 861c2c66affSColin Finck return ERROR_INVALID_FIELD; 862c2c66affSColin Finck 863c2c66affSColin Finck if( rec->fields[iField].type != MSIFIELD_STREAM ) 864c2c66affSColin Finck return ERROR_INVALID_FIELD; 865c2c66affSColin Finck 866c2c66affSColin Finck *pstm = rec->fields[iField].u.stream; 867c2c66affSColin Finck IStream_AddRef( *pstm ); 868c2c66affSColin Finck 869c2c66affSColin Finck return ERROR_SUCCESS; 870c2c66affSColin Finck } 871c2c66affSColin Finck 872c2c66affSColin Finck static UINT msi_dump_stream_to_file( IStream *stm, LPCWSTR name ) 873c2c66affSColin Finck { 874c2c66affSColin Finck ULARGE_INTEGER size; 875c2c66affSColin Finck LARGE_INTEGER pos; 876c2c66affSColin Finck IStream *out; 877c2c66affSColin Finck DWORD stgm; 878c2c66affSColin Finck HRESULT r; 879c2c66affSColin Finck 880c2c66affSColin Finck stgm = STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE; 881c2c66affSColin Finck r = SHCreateStreamOnFileW( name, stgm, &out ); 882c2c66affSColin Finck if( FAILED( r ) ) 883c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 884c2c66affSColin Finck 885c2c66affSColin Finck pos.QuadPart = 0; 886c2c66affSColin Finck r = IStream_Seek( stm, pos, STREAM_SEEK_END, &size ); 887c2c66affSColin Finck if( FAILED( r ) ) 888c2c66affSColin Finck goto end; 889c2c66affSColin Finck 890c2c66affSColin Finck pos.QuadPart = 0; 891c2c66affSColin Finck r = IStream_Seek( stm, pos, STREAM_SEEK_SET, NULL ); 892c2c66affSColin Finck if( FAILED( r ) ) 893c2c66affSColin Finck goto end; 894c2c66affSColin Finck 895c2c66affSColin Finck r = IStream_CopyTo( stm, out, size, NULL, NULL ); 896c2c66affSColin Finck 897c2c66affSColin Finck end: 898c2c66affSColin Finck IStream_Release( out ); 899c2c66affSColin Finck if( FAILED( r ) ) 900c2c66affSColin Finck return ERROR_FUNCTION_FAILED; 901c2c66affSColin Finck return ERROR_SUCCESS; 902c2c66affSColin Finck } 903c2c66affSColin Finck 904c2c66affSColin Finck UINT MSI_RecordStreamToFile( MSIRECORD *rec, UINT iField, LPCWSTR name ) 905c2c66affSColin Finck { 906c2c66affSColin Finck IStream *stm = NULL; 907c2c66affSColin Finck UINT r; 908c2c66affSColin Finck 909c2c66affSColin Finck TRACE("%p %u %s\n", rec, iField, debugstr_w(name)); 910c2c66affSColin Finck 911c2c66affSColin Finck msiobj_lock( &rec->hdr ); 912c2c66affSColin Finck 913c2c66affSColin Finck r = MSI_RecordGetIStream( rec, iField, &stm ); 914c2c66affSColin Finck if( r == ERROR_SUCCESS ) 915c2c66affSColin Finck { 916c2c66affSColin Finck r = msi_dump_stream_to_file( stm, name ); 917c2c66affSColin Finck IStream_Release( stm ); 918c2c66affSColin Finck } 919c2c66affSColin Finck 920c2c66affSColin Finck msiobj_unlock( &rec->hdr ); 921c2c66affSColin Finck 922c2c66affSColin Finck return r; 923c2c66affSColin Finck } 924c2c66affSColin Finck 925c2c66affSColin Finck MSIRECORD *MSI_CloneRecord(MSIRECORD *rec) 926c2c66affSColin Finck { 927c2c66affSColin Finck MSIRECORD *clone; 928c2c66affSColin Finck UINT r, i, count; 929c2c66affSColin Finck 930c2c66affSColin Finck count = MSI_RecordGetFieldCount(rec); 931c2c66affSColin Finck clone = MSI_CreateRecord(count); 932c2c66affSColin Finck if (!clone) 933c2c66affSColin Finck return NULL; 934c2c66affSColin Finck 935c2c66affSColin Finck for (i = 0; i <= count; i++) 936c2c66affSColin Finck { 937c2c66affSColin Finck if (rec->fields[i].type == MSIFIELD_STREAM) 938c2c66affSColin Finck { 939c2c66affSColin Finck if (FAILED(IStream_Clone(rec->fields[i].u.stream, 940c2c66affSColin Finck &clone->fields[i].u.stream))) 941c2c66affSColin Finck { 942c2c66affSColin Finck msiobj_release(&clone->hdr); 943c2c66affSColin Finck return NULL; 944c2c66affSColin Finck } 945c2c66affSColin Finck clone->fields[i].type = MSIFIELD_STREAM; 946c2c66affSColin Finck } 947c2c66affSColin Finck else 948c2c66affSColin Finck { 949c2c66affSColin Finck r = MSI_RecordCopyField(rec, i, clone, i); 950c2c66affSColin Finck if (r != ERROR_SUCCESS) 951c2c66affSColin Finck { 952c2c66affSColin Finck msiobj_release(&clone->hdr); 953c2c66affSColin Finck return NULL; 954c2c66affSColin Finck } 955c2c66affSColin Finck } 956c2c66affSColin Finck } 957c2c66affSColin Finck 958c2c66affSColin Finck return clone; 959c2c66affSColin Finck } 960c2c66affSColin Finck 961c2c66affSColin Finck BOOL MSI_RecordsAreFieldsEqual(MSIRECORD *a, MSIRECORD *b, UINT field) 962c2c66affSColin Finck { 963c2c66affSColin Finck if (a->fields[field].type != b->fields[field].type) 964c2c66affSColin Finck return FALSE; 965c2c66affSColin Finck 966c2c66affSColin Finck switch (a->fields[field].type) 967c2c66affSColin Finck { 968c2c66affSColin Finck case MSIFIELD_NULL: 969c2c66affSColin Finck break; 970c2c66affSColin Finck 971c2c66affSColin Finck case MSIFIELD_INT: 972c2c66affSColin Finck if (a->fields[field].u.iVal != b->fields[field].u.iVal) 973c2c66affSColin Finck return FALSE; 974c2c66affSColin Finck break; 975c2c66affSColin Finck 976c2c66affSColin Finck case MSIFIELD_WSTR: 977c2c66affSColin Finck if (a->fields[field].len != b->fields[field].len) return FALSE; 978c2c66affSColin Finck if (memcmp( a->fields[field].u.szwVal, b->fields[field].u.szwVal, 979c2c66affSColin Finck a->fields[field].len * sizeof(WCHAR) )) return FALSE; 980c2c66affSColin Finck break; 981c2c66affSColin Finck 982c2c66affSColin Finck case MSIFIELD_STREAM: 983c2c66affSColin Finck default: 984c2c66affSColin Finck return FALSE; 985c2c66affSColin Finck } 986c2c66affSColin Finck return TRUE; 987c2c66affSColin Finck } 988c2c66affSColin Finck 989c2c66affSColin Finck 990c2c66affSColin Finck BOOL MSI_RecordsAreEqual(MSIRECORD *a, MSIRECORD *b) 991c2c66affSColin Finck { 992c2c66affSColin Finck UINT i; 993c2c66affSColin Finck 994c2c66affSColin Finck if (a->count != b->count) 995c2c66affSColin Finck return FALSE; 996c2c66affSColin Finck 997c2c66affSColin Finck for (i = 0; i <= a->count; i++) 998c2c66affSColin Finck { 999c2c66affSColin Finck if (!MSI_RecordsAreFieldsEqual( a, b, i )) 1000c2c66affSColin Finck return FALSE; 1001c2c66affSColin Finck } 1002c2c66affSColin Finck 1003c2c66affSColin Finck return TRUE; 1004c2c66affSColin Finck } 1005c2c66affSColin Finck 1006c2c66affSColin Finck WCHAR *msi_dup_record_field( MSIRECORD *rec, INT field ) 1007c2c66affSColin Finck { 1008c2c66affSColin Finck DWORD sz = 0; 1009c2c66affSColin Finck WCHAR *str; 1010c2c66affSColin Finck UINT r; 1011c2c66affSColin Finck 1012c2c66affSColin Finck if (MSI_RecordIsNull( rec, field )) return NULL; 1013c2c66affSColin Finck 1014c2c66affSColin Finck r = MSI_RecordGetStringW( rec, field, NULL, &sz ); 1015c2c66affSColin Finck if (r != ERROR_SUCCESS) 1016c2c66affSColin Finck return NULL; 1017c2c66affSColin Finck 1018c2c66affSColin Finck sz++; 1019c2c66affSColin Finck str = msi_alloc( sz * sizeof(WCHAR) ); 1020c2c66affSColin Finck if (!str) return NULL; 1021c2c66affSColin Finck str[0] = 0; 1022c2c66affSColin Finck r = MSI_RecordGetStringW( rec, field, str, &sz ); 1023c2c66affSColin Finck if (r != ERROR_SUCCESS) 1024c2c66affSColin Finck { 1025c2c66affSColin Finck ERR("failed to get string!\n"); 1026c2c66affSColin Finck msi_free( str ); 1027c2c66affSColin Finck return NULL; 1028c2c66affSColin Finck } 1029c2c66affSColin Finck return str; 1030c2c66affSColin Finck } 103171bffdcdSAmine Khaldi 103271bffdcdSAmine Khaldi void dump_record(MSIRECORD *rec) 103371bffdcdSAmine Khaldi { 103471bffdcdSAmine Khaldi int i; 103571bffdcdSAmine Khaldi if (!rec) 103671bffdcdSAmine Khaldi { 103771bffdcdSAmine Khaldi TRACE("(null)\n"); 103871bffdcdSAmine Khaldi return; 103971bffdcdSAmine Khaldi } 104071bffdcdSAmine Khaldi 104171bffdcdSAmine Khaldi TRACE("["); 104271bffdcdSAmine Khaldi for (i = 0; i <= rec->count; i++) 104371bffdcdSAmine Khaldi { 104471bffdcdSAmine Khaldi switch(rec->fields[i].type) 104571bffdcdSAmine Khaldi { 104671bffdcdSAmine Khaldi case MSIFIELD_NULL: TRACE("(null)"); break; 104771bffdcdSAmine Khaldi case MSIFIELD_INT: TRACE("%d", rec->fields[i].u.iVal); break; 104871bffdcdSAmine Khaldi case MSIFIELD_WSTR: TRACE("%s", debugstr_w(rec->fields[i].u.szwVal)); break; 104971bffdcdSAmine Khaldi case MSIFIELD_STREAM: TRACE("%p", rec->fields[i].u.stream); break; 105071bffdcdSAmine Khaldi } 105171bffdcdSAmine Khaldi if (i < rec->count) TRACE(", "); 105271bffdcdSAmine Khaldi } 105371bffdcdSAmine Khaldi TRACE("]\n"); 105471bffdcdSAmine Khaldi } 10552e19edd6Swinesync 1056aede536cSwinesync UINT copy_remote_record(const struct wire_record *in, MSIHANDLE out) 10572e19edd6Swinesync { 10582e19edd6Swinesync MSIRECORD *rec; 10592e19edd6Swinesync unsigned int i; 10608c04add1Swinesync UINT r = ERROR_SUCCESS; 10612e19edd6Swinesync 1062aede536cSwinesync if (!(rec = msihandle2msiinfo(out, MSIHANDLETYPE_RECORD))) 1063aede536cSwinesync return ERROR_INVALID_HANDLE; 10642e19edd6Swinesync 106514478462Swinesync rec->cookie = in->cookie; 10662e19edd6Swinesync for (i = 0; i <= in->count; i++) 10672e19edd6Swinesync { 10682e19edd6Swinesync switch (in->fields[i].type) 10692e19edd6Swinesync { 10702e19edd6Swinesync case MSIFIELD_NULL: 1071aede536cSwinesync MSI_FreeField(&rec->fields[i]); 1072aede536cSwinesync rec->fields[i].type = MSIFIELD_NULL; 10732e19edd6Swinesync break; 10742e19edd6Swinesync case MSIFIELD_INT: 10752e19edd6Swinesync r = MSI_RecordSetInteger(rec, i, in->fields[i].u.iVal); 10762e19edd6Swinesync break; 10772e19edd6Swinesync case MSIFIELD_WSTR: 10782e19edd6Swinesync r = MSI_RecordSetStringW(rec, i, in->fields[i].u.szwVal); 10792e19edd6Swinesync break; 10802e19edd6Swinesync case MSIFIELD_STREAM: 10812e19edd6Swinesync r = MSI_RecordSetIStream(rec, i, in->fields[i].u.stream); 10822e19edd6Swinesync break; 10832e19edd6Swinesync default: 10842e19edd6Swinesync ERR("invalid field type %d\n", in->fields[i].type); 10852e19edd6Swinesync break; 10862e19edd6Swinesync } 10872e19edd6Swinesync 10882e19edd6Swinesync if (r) 10892e19edd6Swinesync { 10902e19edd6Swinesync msiobj_release(&rec->hdr); 10912e19edd6Swinesync return r; 10922e19edd6Swinesync } 10932e19edd6Swinesync } 10942e19edd6Swinesync 10952e19edd6Swinesync msiobj_release(&rec->hdr); 10962e19edd6Swinesync return ERROR_SUCCESS; 10972e19edd6Swinesync } 1098795da528Swinesync 1099aede536cSwinesync UINT unmarshal_record(const struct wire_record *in, MSIHANDLE *out) 1100aede536cSwinesync { 1101aede536cSwinesync if (!in) 1102aede536cSwinesync { 1103aede536cSwinesync *out = 0; 1104aede536cSwinesync return ERROR_SUCCESS; 1105aede536cSwinesync } 1106aede536cSwinesync 1107aede536cSwinesync *out = MsiCreateRecord(in->count); 1108aede536cSwinesync if (!*out) return ERROR_OUTOFMEMORY; 1109aede536cSwinesync 1110aede536cSwinesync return copy_remote_record(in, *out); 1111aede536cSwinesync } 1112aede536cSwinesync 1113795da528Swinesync struct wire_record *marshal_record(MSIHANDLE handle) 1114795da528Swinesync { 1115795da528Swinesync struct wire_record *ret; 111614478462Swinesync unsigned int i; 1117795da528Swinesync MSIRECORD *rec; 1118795da528Swinesync 1119795da528Swinesync if (!(rec = msihandle2msiinfo(handle, MSIHANDLETYPE_RECORD))) 1120795da528Swinesync return NULL; 1121795da528Swinesync 112214478462Swinesync ret = midl_user_allocate(sizeof(*ret) + rec->count * sizeof(ret->fields[0])); 112314478462Swinesync ret->count = rec->count; 112414478462Swinesync ret->cookie = rec->cookie; 1125795da528Swinesync 112614478462Swinesync for (i = 0; i <= rec->count; i++) 1127795da528Swinesync { 1128795da528Swinesync switch (rec->fields[i].type) 1129795da528Swinesync { 1130795da528Swinesync case MSIFIELD_NULL: 1131795da528Swinesync break; 1132795da528Swinesync case MSIFIELD_INT: 1133795da528Swinesync ret->fields[i].u.iVal = rec->fields[i].u.iVal; 1134795da528Swinesync break; 1135795da528Swinesync case MSIFIELD_WSTR: 1136795da528Swinesync ret->fields[i].u.szwVal = strdupW(rec->fields[i].u.szwVal); 1137795da528Swinesync break; 1138795da528Swinesync case MSIFIELD_STREAM: 1139795da528Swinesync IStream_AddRef(rec->fields[i].u.stream); 1140795da528Swinesync ret->fields[i].u.stream = rec->fields[i].u.stream; 1141795da528Swinesync break; 1142795da528Swinesync default: 1143795da528Swinesync ERR("invalid field type %d\n", rec->fields[i].type); 1144795da528Swinesync break; 1145795da528Swinesync } 1146795da528Swinesync ret->fields[i].type = rec->fields[i].type; 1147795da528Swinesync } 1148795da528Swinesync 1149795da528Swinesync msiobj_release(&rec->hdr); 1150795da528Swinesync return ret; 1151795da528Swinesync } 1152795da528Swinesync 1153795da528Swinesync void free_remote_record(struct wire_record *rec) 1154795da528Swinesync { 1155795da528Swinesync int i; 1156795da528Swinesync 1157795da528Swinesync for (i = 0; i <= rec->count; i++) 1158795da528Swinesync { 1159795da528Swinesync if (rec->fields[i].type == MSIFIELD_WSTR) 1160795da528Swinesync midl_user_free(rec->fields[i].u.szwVal); 1161795da528Swinesync else if (rec->fields[i].type == MSIFIELD_STREAM) 1162795da528Swinesync IStream_Release(rec->fields[i].u.stream); 1163795da528Swinesync } 1164795da528Swinesync 1165795da528Swinesync midl_user_free(rec); 1166795da528Swinesync } 1167