msi: Store the _Columns and _Tables tables in the database structure.
This commit is contained in:
parent
3bec162d51
commit
4b9fd1d5e2
|
@ -204,7 +204,6 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
|
|||
if( !db->strings )
|
||||
goto end;
|
||||
|
||||
msi_table_set_strref( db->bytes_per_strref );
|
||||
ret = ERROR_SUCCESS;
|
||||
|
||||
msiobj_addref( &db->hdr );
|
||||
|
|
|
@ -656,8 +656,6 @@ extern HRESULT msi_init_string_table( IStorage *stg );
|
|||
extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref );
|
||||
extern UINT msi_save_string_table( const string_table *st, IStorage *storage );
|
||||
|
||||
|
||||
extern void msi_table_set_strref(UINT bytes_per_strref);
|
||||
extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name );
|
||||
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table );
|
||||
|
||||
|
|
111
dlls/msi/table.c
111
dlls/msi/table.c
|
@ -101,16 +101,14 @@ static WCHAR szColumns[] = { '_','C','o','l','u','m','n','s',0 };
|
|||
static WCHAR szNumber[] = { 'N','u','m','b','e','r',0 };
|
||||
static WCHAR szType[] = { 'T','y','p','e',0 };
|
||||
|
||||
/* These tables are written into (the .hash_table part).
|
||||
* Do not mark them const.
|
||||
*/
|
||||
static MSICOLUMNINFO _Columns_cols[4] = {
|
||||
static const MSICOLUMNINFO _Columns_cols[4] = {
|
||||
{ szColumns, 1, szTable, MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, 0, NULL },
|
||||
{ szColumns, 2, szNumber, MSITYPE_VALID | MSITYPE_KEY | 2, 2, 0, NULL },
|
||||
{ szColumns, 3, szName, MSITYPE_VALID | MSITYPE_STRING | 64, 4, 0, NULL },
|
||||
{ szColumns, 4, szType, MSITYPE_VALID | 2, 6, 0, NULL },
|
||||
};
|
||||
static MSICOLUMNINFO _Tables_cols[1] = {
|
||||
|
||||
static const MSICOLUMNINFO _Tables_cols[1] = {
|
||||
{ szTables, 1, szName, MSITYPE_VALID | MSITYPE_STRING | 64, 0, 0, NULL },
|
||||
};
|
||||
|
||||
|
@ -118,26 +116,18 @@ static MSICOLUMNINFO _Tables_cols[1] = {
|
|||
|
||||
static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name,
|
||||
MSICOLUMNINFO **pcols, UINT *pcount );
|
||||
static void table_calc_column_offsets( MSICOLUMNINFO *colinfo, DWORD count );
|
||||
static void table_calc_column_offsets( MSIDATABASE *db, MSICOLUMNINFO *colinfo,
|
||||
DWORD count );
|
||||
static UINT get_tablecolumns( MSIDATABASE *db,
|
||||
LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz);
|
||||
static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count );
|
||||
|
||||
|
||||
void msi_table_set_strref(UINT bytes_per_strref)
|
||||
{
|
||||
_Columns_cols[0].offset = 0;
|
||||
_Columns_cols[1].offset = bytes_per_strref;
|
||||
_Columns_cols[2].offset = _Columns_cols[1].offset + sizeof(USHORT);
|
||||
_Columns_cols[3].offset = _Columns_cols[2].offset + bytes_per_strref;
|
||||
}
|
||||
|
||||
static inline UINT bytes_per_column( const MSICOLUMNINFO *col )
|
||||
static inline UINT bytes_per_column( MSIDATABASE *db, const MSICOLUMNINFO *col )
|
||||
{
|
||||
if( MSITYPE_IS_BINARY(col->type) )
|
||||
return 2;
|
||||
if( col->type & MSITYPE_STRING )
|
||||
return _Columns_cols[1].offset;
|
||||
return db->bytes_per_strref;
|
||||
if( (col->type & 0xff) > 4 )
|
||||
ERR("Invalid column size!\n");
|
||||
return col->type & 0xff;
|
||||
|
@ -488,32 +478,29 @@ static void free_table( MSITABLE *table )
|
|||
for( i=0; i<table->nonpersistent_row_count; i++ )
|
||||
msi_free( table->nonpersistent_data[i] );
|
||||
msi_free( table->nonpersistent_data );
|
||||
if( (table->colinfo != _Tables_cols) &&
|
||||
(table->colinfo != _Columns_cols) )
|
||||
{
|
||||
msi_free_colinfo( table->colinfo, table->col_count );
|
||||
msi_free( table->colinfo );
|
||||
}
|
||||
msi_free_colinfo( table->colinfo, table->col_count );
|
||||
msi_free( table->colinfo );
|
||||
msi_free( table );
|
||||
}
|
||||
|
||||
static UINT msi_table_get_row_size( const MSICOLUMNINFO *cols, UINT count )
|
||||
static UINT msi_table_get_row_size( MSIDATABASE *db,const MSICOLUMNINFO *cols,
|
||||
UINT count )
|
||||
{
|
||||
const MSICOLUMNINFO *last_col = &cols[count-1];
|
||||
if (!count)
|
||||
return 0;
|
||||
return last_col->offset + bytes_per_column( last_col );
|
||||
return last_col->offset + bytes_per_column( db, last_col );
|
||||
}
|
||||
|
||||
/* add this table to the list of cached tables in the database */
|
||||
static UINT read_table_from_storage( MSITABLE *t, IStorage *stg )
|
||||
static UINT read_table_from_storage( MSIDATABASE *db, MSITABLE *t, IStorage *stg )
|
||||
{
|
||||
BYTE *rawdata = NULL;
|
||||
UINT rawsize = 0, i, j, row_size = 0;
|
||||
|
||||
TRACE("%s\n",debugstr_w(t->name));
|
||||
|
||||
row_size = msi_table_get_row_size( t->colinfo, t->col_count );
|
||||
row_size = msi_table_get_row_size( db, t->colinfo, t->col_count );
|
||||
|
||||
/* if we can't read the table, just assume that it's empty */
|
||||
read_stream_data( stg, t->name, TRUE, &rawdata, &rawsize );
|
||||
|
@ -544,7 +531,7 @@ static UINT read_table_from_storage( MSITABLE *t, IStorage *stg )
|
|||
for( j=0; j<t->col_count; j++ )
|
||||
{
|
||||
UINT ofs = t->colinfo[j].offset;
|
||||
UINT n = bytes_per_column( &t->colinfo[j] );
|
||||
UINT n = bytes_per_column( db, &t->colinfo[j] );
|
||||
UINT k;
|
||||
|
||||
if ( n != 2 && n != 3 && n != 4 )
|
||||
|
@ -672,7 +659,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
|||
table->colinfo[ i ].ref_count = 0;
|
||||
table->colinfo[ i ].hash_table = NULL;
|
||||
}
|
||||
table_calc_column_offsets( table->colinfo, table->col_count);
|
||||
table_calc_column_offsets( db, table->colinfo, table->col_count);
|
||||
|
||||
r = TABLE_CreateView( db, szTables, &tv );
|
||||
TRACE("CreateView returned %x\n", r);
|
||||
|
@ -800,28 +787,14 @@ static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
|
|||
table->persistent = TRUE;
|
||||
lstrcpyW( table->name, name );
|
||||
|
||||
/* these two tables are special - we know the column types already */
|
||||
if( !lstrcmpW( name, szColumns ) )
|
||||
r = table_get_column_info( db, name, &table->colinfo, &table->col_count);
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
table->colinfo = _Columns_cols;
|
||||
table->col_count = sizeof(_Columns_cols)/sizeof(_Columns_cols[0]);
|
||||
}
|
||||
else if( !lstrcmpW( name, szTables ) )
|
||||
{
|
||||
table->colinfo = _Tables_cols;
|
||||
table->col_count = sizeof(_Tables_cols)/sizeof(_Tables_cols[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = table_get_column_info( db, name, &table->colinfo, &table->col_count);
|
||||
if (r != ERROR_SUCCESS)
|
||||
{
|
||||
free_table ( table );
|
||||
return r;
|
||||
}
|
||||
free_table ( table );
|
||||
return r;
|
||||
}
|
||||
|
||||
r = read_table_from_storage( table, db->storage );
|
||||
r = read_table_from_storage( db, table, db->storage );
|
||||
if( r != ERROR_SUCCESS )
|
||||
{
|
||||
free_table( table );
|
||||
|
@ -844,7 +817,7 @@ static UINT save_table( MSIDATABASE *db, const MSITABLE *t )
|
|||
|
||||
TRACE("Saving %s\n", debugstr_w( t->name ) );
|
||||
|
||||
row_size = msi_table_get_row_size( t->colinfo, t->col_count );
|
||||
row_size = msi_table_get_row_size( db, t->colinfo, t->col_count );
|
||||
|
||||
rawsize = t->row_count * row_size;
|
||||
rawdata = msi_alloc_zero( rawsize );
|
||||
|
@ -863,7 +836,7 @@ static UINT save_table( MSIDATABASE *db, const MSITABLE *t )
|
|||
|
||||
*p++ = t->data[j][offset];
|
||||
*p++ = t->data[j][offset + 1];
|
||||
if( 4 == bytes_per_column( &t->colinfo[i] ) )
|
||||
if( 4 == bytes_per_column( db, &t->colinfo[i] ) )
|
||||
{
|
||||
*p++ = t->data[j][offset + 2];
|
||||
*p++ = t->data[j][offset + 3];
|
||||
|
@ -880,7 +853,8 @@ err:
|
|||
return r;
|
||||
}
|
||||
|
||||
static void table_calc_column_offsets( MSICOLUMNINFO *colinfo, DWORD count )
|
||||
static void table_calc_column_offsets( MSIDATABASE *db, MSICOLUMNINFO *colinfo,
|
||||
DWORD count )
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
|
@ -889,7 +863,7 @@ static void table_calc_column_offsets( MSICOLUMNINFO *colinfo, DWORD count )
|
|||
assert( (i+1) == colinfo[ i ].number );
|
||||
if (i)
|
||||
colinfo[i].offset = colinfo[ i - 1 ].offset
|
||||
+ bytes_per_column( &colinfo[ i - 1 ] );
|
||||
+ bytes_per_column( db, &colinfo[ i - 1 ] );
|
||||
else
|
||||
colinfo[i].offset = 0;
|
||||
TRACE("column %d is [%s] with type %08x ofs %d\n",
|
||||
|
@ -898,7 +872,8 @@ static void table_calc_column_offsets( MSICOLUMNINFO *colinfo, DWORD count )
|
|||
}
|
||||
}
|
||||
|
||||
static UINT get_defaulttablecolumns( LPCWSTR name, MSICOLUMNINFO *colinfo, UINT *sz)
|
||||
static UINT get_defaulttablecolumns( MSIDATABASE *db, LPCWSTR name,
|
||||
MSICOLUMNINFO *colinfo, UINT *sz)
|
||||
{
|
||||
const MSICOLUMNINFO *p;
|
||||
DWORD i, n;
|
||||
|
@ -930,7 +905,7 @@ static UINT get_defaulttablecolumns( LPCWSTR name, MSICOLUMNINFO *colinfo, UINT
|
|||
if( colinfo && (i >= *sz) )
|
||||
break;
|
||||
}
|
||||
table_calc_column_offsets( colinfo, n );
|
||||
table_calc_column_offsets( db, colinfo, n );
|
||||
*sz = n;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
@ -971,7 +946,7 @@ static UINT get_tablecolumns( MSIDATABASE *db,
|
|||
TRACE("%s\n", debugstr_w(szTableName));
|
||||
|
||||
/* first check if there is a default table with that name */
|
||||
r = get_defaulttablecolumns( szTableName, colinfo, sz );
|
||||
r = get_defaulttablecolumns( db, szTableName, colinfo, sz );
|
||||
if( ( r == ERROR_SUCCESS ) && *sz )
|
||||
return r;
|
||||
|
||||
|
@ -1003,8 +978,8 @@ static UINT get_tablecolumns( MSIDATABASE *db,
|
|||
continue;
|
||||
if( colinfo )
|
||||
{
|
||||
UINT id = read_table_int(table->data, i, _Columns_cols[2].offset, db->bytes_per_strref);
|
||||
UINT col = read_table_int(table->data, i, _Columns_cols[1].offset, sizeof(USHORT)) - (1<<15);
|
||||
UINT id = read_table_int(table->data, i, table->colinfo[2].offset, db->bytes_per_strref);
|
||||
UINT col = read_table_int(table->data, i, table->colinfo[1].offset, sizeof(USHORT)) - (1<<15);
|
||||
|
||||
/* check the column number is in range */
|
||||
if (col<1 || col>maxcount)
|
||||
|
@ -1023,7 +998,9 @@ static UINT get_tablecolumns( MSIDATABASE *db,
|
|||
colinfo[ col - 1 ].tablename = msi_makestring( db, table_id );
|
||||
colinfo[ col - 1 ].number = col;
|
||||
colinfo[ col - 1 ].colname = msi_makestring( db, id );
|
||||
colinfo[ col - 1 ].type = read_table_int(table->data, i, _Columns_cols[3].offset, sizeof(USHORT)) - (1<<15);
|
||||
colinfo[ col - 1 ].type = read_table_int(table->data, i,
|
||||
table->colinfo[3].offset,
|
||||
sizeof(USHORT)) - (1<<15);
|
||||
colinfo[ col - 1 ].offset = 0;
|
||||
colinfo[ col - 1 ].ref_count = 0;
|
||||
colinfo[ col - 1 ].hash_table = NULL;
|
||||
|
@ -1040,7 +1017,7 @@ static UINT get_tablecolumns( MSIDATABASE *db,
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
table_calc_column_offsets( colinfo, n );
|
||||
table_calc_column_offsets( db, colinfo, n );
|
||||
*sz = n;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -1057,7 +1034,7 @@ static void msi_update_table_columns( MSIDATABASE *db, LPCWSTR name )
|
|||
msi_free( table->colinfo );
|
||||
table_get_column_info( db, name, &table->colinfo, &table->col_count );
|
||||
|
||||
size = msi_table_get_row_size( table->colinfo, table->col_count );
|
||||
size = msi_table_get_row_size( db, table->colinfo, table->col_count );
|
||||
offset = table->colinfo[table->col_count - 1].offset;
|
||||
|
||||
for ( n = 0; n < table->row_count; n++ )
|
||||
|
@ -1162,7 +1139,7 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
|
|||
else
|
||||
data = tv->table->data;
|
||||
|
||||
n = bytes_per_column( &tv->columns[col-1] );
|
||||
n = bytes_per_column( tv->db, &tv->columns[col-1] );
|
||||
if (n != 2 && n != 3 && n != 4)
|
||||
{
|
||||
ERR("oops! what is %d bytes per column?\n", n );
|
||||
|
@ -1277,7 +1254,7 @@ static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val )
|
|||
else
|
||||
data = tv->table->data;
|
||||
|
||||
n = bytes_per_column( &tv->columns[col-1] );
|
||||
n = bytes_per_column( tv->db, &tv->columns[col-1] );
|
||||
if ( n != 2 && n != 3 && n != 4 )
|
||||
{
|
||||
ERR("oops! what is %d bytes per column?\n", n );
|
||||
|
@ -1351,7 +1328,7 @@ static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UI
|
|||
val = msi_addstringW( tv->db->strings, 0, sval, -1, 1,
|
||||
persistent ? StringPersistent : StringNonPersistent );
|
||||
}
|
||||
else if ( 2 == bytes_per_column( &tv->columns[ i ] ) )
|
||||
else if ( 2 == bytes_per_column( tv->db, &tv->columns[ i ] ) )
|
||||
{
|
||||
val = 0x8000 + MSI_RecordGetInteger( rec, i + 1 );
|
||||
if ( val & 0xffff0000 )
|
||||
|
@ -2138,7 +2115,7 @@ UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
|
|||
tv->db = db;
|
||||
tv->columns = tv->table->colinfo;
|
||||
tv->num_cols = tv->table->col_count;
|
||||
tv->row_size = msi_table_get_row_size( tv->table->colinfo, tv->table->col_count );
|
||||
tv->row_size = msi_table_get_row_size( db, tv->table->colinfo, tv->table->col_count );
|
||||
|
||||
TRACE("%s one row is %d bytes\n", debugstr_w(name), tv->row_size );
|
||||
|
||||
|
@ -2246,7 +2223,7 @@ static MSIRECORD *msi_get_transform_record( const MSITABLEVIEW *tv, const string
|
|||
}
|
||||
else
|
||||
{
|
||||
UINT n = bytes_per_column( &columns[i] );
|
||||
UINT n = bytes_per_column( tv->db, &columns[i] );
|
||||
switch( n )
|
||||
{
|
||||
case 2:
|
||||
|
@ -2457,7 +2434,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||
sz += bytes_per_strref;
|
||||
else
|
||||
sz += bytes_per_column( &tv->columns[i] );
|
||||
sz += bytes_per_column( tv->db, &tv->columns[i] );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2479,7 +2456,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
! MSITYPE_IS_BINARY(tv->columns[i].type) )
|
||||
sz += bytes_per_strref;
|
||||
else
|
||||
sz += bytes_per_column( &tv->columns[i] );
|
||||
sz += bytes_per_column( tv->db, &tv->columns[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue