msi: Add support for exporting binary streams (Binary/Icon tables).
The Binary and Icon tables store their data in a different format from other tables, one column of the data is stored as a "stream" instead of a normal text field. With this patch those tables can now be exported properly by the MSI export functionality. Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com> Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b08d999863
commit
f1d8218169
|
@ -961,8 +961,68 @@ static UINT msi_export_field( HANDLE handle, MSIRECORD *row, UINT field )
|
|||
return ret ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
|
||||
static UINT msi_export_stream( const WCHAR *folder, const WCHAR *table, MSIRECORD *row, UINT field, UINT start )
|
||||
{
|
||||
static const WCHAR fmt[] = {'%','s','\\','%','s',0};
|
||||
WCHAR stream[MAX_STREAM_NAME_LEN + 1], *path;
|
||||
DWORD sz, read_size, write_size;
|
||||
char buffer[1024];
|
||||
HANDLE file;
|
||||
UINT len, r;
|
||||
|
||||
sz = ARRAY_SIZE( stream );
|
||||
r = MSI_RecordGetStringW( row, start, stream, &sz );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
len = (sz + strlenW( folder ) + strlenW( table ) + ARRAY_SIZE( fmt ) + 1) * sizeof(WCHAR);
|
||||
if (!(path = msi_alloc( len )))
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
len = sprintfW( path, fmt, folder, table );
|
||||
if (!CreateDirectoryW( path, NULL ) && GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
msi_free( path );
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
path[len++] = '\\';
|
||||
strcpyW( path + len, stream );
|
||||
file = CreateFileW( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
msi_free( path );
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
read_size = sizeof(buffer);
|
||||
while (read_size == sizeof(buffer))
|
||||
{
|
||||
r = MSI_RecordReadStream( row, field, buffer, &read_size );
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
CloseHandle( file );
|
||||
return r;
|
||||
}
|
||||
if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
|
||||
{
|
||||
CloseHandle( file );
|
||||
return ERROR_WRITE_FAULT;
|
||||
}
|
||||
}
|
||||
CloseHandle( file );
|
||||
return r;
|
||||
}
|
||||
|
||||
struct row_export_info
|
||||
{
|
||||
HANDLE handle;
|
||||
const WCHAR *folder;
|
||||
const WCHAR *table;
|
||||
};
|
||||
|
||||
static UINT msi_export_record( struct row_export_info *row_export_info, MSIRECORD *row, UINT start )
|
||||
{
|
||||
HANDLE handle = row_export_info->handle;
|
||||
UINT i, count, r = ERROR_SUCCESS;
|
||||
const char *sep;
|
||||
DWORD sz;
|
||||
|
@ -971,7 +1031,18 @@ static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
|
|||
for (i = start; i <= count; i++)
|
||||
{
|
||||
r = msi_export_field( handle, row, i );
|
||||
if (r != ERROR_SUCCESS)
|
||||
if (r == ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
r = msi_export_stream( row_export_info->folder, row_export_info->table, row, i, start );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
/* exporting a binary stream, repeat the "Name" field */
|
||||
r = msi_export_field( handle, row, start );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
}
|
||||
else if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
sep = (i < count) ? "\t" : "\r\n";
|
||||
|
@ -1062,11 +1133,13 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table, LPCWSTR folder,
|
|||
r = MSI_OpenQuery( db, &view, query, table );
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
struct row_export_info row_export_info = { handle, folder, table };
|
||||
|
||||
/* write out row 1, the column names */
|
||||
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
msi_export_record( handle, rec, 1 );
|
||||
msi_export_record( &row_export_info, rec, 1 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
|
@ -1074,7 +1147,7 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table, LPCWSTR folder,
|
|||
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
msi_export_record( handle, rec, 1 );
|
||||
msi_export_record( &row_export_info, rec, 1 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
|
@ -1083,12 +1156,12 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table, LPCWSTR folder,
|
|||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
MSI_RecordSetStringW( rec, 0, table );
|
||||
msi_export_record( handle, rec, 0 );
|
||||
msi_export_record( &row_export_info, rec, 0 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
/* write out row 4 onwards, the data */
|
||||
r = MSI_IterateRecords( view, 0, msi_export_row, handle );
|
||||
r = MSI_IterateRecords( view, 0, msi_export_row, &row_export_info );
|
||||
msiobj_release( &view->hdr );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue