Commit 4b9fd1d5 authored by James Hawkins's avatar James Hawkins Committed by Alexandre Julliard

msi: Store the _Columns and _Tables tables in the database structure.

parent 3bec162d
......@@ -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 );
......
......@@ -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( 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 ) )
{
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;
}
}
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] );
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment