msi: Get rid of some more forward declarations.
This commit is contained in:
parent
4004b25c1d
commit
1ae309f981
|
@ -153,7 +153,24 @@ static const WCHAR szProperty[] = {'P','r','o','p','e','r','t','y',0};
|
||||||
static DWORD uiThreadId;
|
static DWORD uiThreadId;
|
||||||
static HWND hMsiHiddenWindow;
|
static HWND hMsiHiddenWindow;
|
||||||
|
|
||||||
static LPWSTR msi_get_window_text( HWND hwnd );
|
static LPWSTR msi_get_window_text( HWND hwnd )
|
||||||
|
{
|
||||||
|
UINT sz, r;
|
||||||
|
LPWSTR buf;
|
||||||
|
|
||||||
|
sz = 0x20;
|
||||||
|
buf = msi_alloc( sz*sizeof(WCHAR) );
|
||||||
|
while ( buf )
|
||||||
|
{
|
||||||
|
r = GetWindowTextW( hwnd, buf, sz );
|
||||||
|
if ( r < (sz - 1) )
|
||||||
|
break;
|
||||||
|
sz *= 2;
|
||||||
|
buf = msi_realloc( buf, sz*sizeof(WCHAR) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
static INT msi_dialog_scale_unit( msi_dialog *dialog, INT val )
|
static INT msi_dialog_scale_unit( msi_dialog *dialog, INT val )
|
||||||
{
|
{
|
||||||
|
@ -2044,25 +2061,6 @@ struct msi_pathedit_info
|
||||||
WNDPROC oldproc;
|
WNDPROC oldproc;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LPWSTR msi_get_window_text( HWND hwnd )
|
|
||||||
{
|
|
||||||
UINT sz, r;
|
|
||||||
LPWSTR buf;
|
|
||||||
|
|
||||||
sz = 0x20;
|
|
||||||
buf = msi_alloc( sz*sizeof(WCHAR) );
|
|
||||||
while ( buf )
|
|
||||||
{
|
|
||||||
r = GetWindowTextW( hwnd, buf, sz );
|
|
||||||
if ( r < (sz - 1) )
|
|
||||||
break;
|
|
||||||
sz *= 2;
|
|
||||||
buf = msi_realloc( buf, sz*sizeof(WCHAR) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control )
|
static void msi_dialog_update_pathedit( msi_dialog *dialog, msi_control *control )
|
||||||
{
|
{
|
||||||
LPWSTR prop, path;
|
LPWSTR prop, path;
|
||||||
|
|
443
dlls/msi/table.c
443
dlls/msi/table.c
|
@ -103,14 +103,6 @@ static const MSICOLUMNINFO _Tables_cols[1] = {
|
||||||
|
|
||||||
#define MAX_STREAM_NAME 0x1f
|
#define MAX_STREAM_NAME 0x1f
|
||||||
|
|
||||||
static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name,
|
|
||||||
MSICOLUMNINFO **pcols, UINT *pcount );
|
|
||||||
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 );
|
|
||||||
|
|
||||||
static inline UINT bytes_per_column( MSIDATABASE *db, const MSICOLUMNINFO *col, UINT bytes_per_strref )
|
static inline UINT bytes_per_column( MSIDATABASE *db, const MSICOLUMNINFO *col, UINT bytes_per_strref )
|
||||||
{
|
{
|
||||||
if( MSITYPE_IS_BINARY(col->type) )
|
if( MSITYPE_IS_BINARY(col->type) )
|
||||||
|
@ -381,6 +373,18 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count )
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
msi_free( colinfo[i].tablename );
|
||||||
|
msi_free( colinfo[i].colname );
|
||||||
|
msi_free( colinfo[i].hash_table );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void free_table( MSITABLE *table )
|
static void free_table( MSITABLE *table )
|
||||||
{
|
{
|
||||||
UINT i;
|
UINT i;
|
||||||
|
@ -513,6 +517,60 @@ static MSITABLE *find_cached_table( MSIDATABASE *db, LPCWSTR name )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void table_calc_column_offsets( MSIDATABASE *db, MSICOLUMNINFO *colinfo, DWORD count )
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
for (i = 0; colinfo && i < count; i++)
|
||||||
|
{
|
||||||
|
assert( i + 1 == colinfo[i].number );
|
||||||
|
if (i) colinfo[i].offset = colinfo[i - 1].offset +
|
||||||
|
bytes_per_column( db, &colinfo[i - 1], LONG_STR_BYTES );
|
||||||
|
else colinfo[i].offset = 0;
|
||||||
|
|
||||||
|
TRACE("column %d is [%s] with type %08x ofs %d\n",
|
||||||
|
colinfo[i].number, debugstr_w(colinfo[i].colname),
|
||||||
|
colinfo[i].type, colinfo[i].offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT get_defaulttablecolumns( MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO *colinfo, UINT *sz )
|
||||||
|
{
|
||||||
|
const MSICOLUMNINFO *p;
|
||||||
|
DWORD i, n;
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_w(name));
|
||||||
|
|
||||||
|
if (!strcmpW( name, szTables ))
|
||||||
|
{
|
||||||
|
p = _Tables_cols;
|
||||||
|
n = 1;
|
||||||
|
}
|
||||||
|
else if (!strcmpW( name, szColumns ))
|
||||||
|
{
|
||||||
|
p = _Columns_cols;
|
||||||
|
n = 4;
|
||||||
|
}
|
||||||
|
else return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
/* duplicate the string data so we can free it in msi_free_colinfo */
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (colinfo && i < *sz)
|
||||||
|
{
|
||||||
|
colinfo[i] = p[i];
|
||||||
|
colinfo[i].tablename = strdupW( p[i].tablename );
|
||||||
|
colinfo[i].colname = strdupW( p[i].colname );
|
||||||
|
}
|
||||||
|
if (colinfo && i >= *sz) break;
|
||||||
|
}
|
||||||
|
table_calc_column_offsets( db, colinfo, n );
|
||||||
|
*sz = n;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz );
|
||||||
|
|
||||||
static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO **pcols, UINT *pcount )
|
static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO **pcols, UINT *pcount )
|
||||||
{
|
{
|
||||||
UINT r, column_count = 0;
|
UINT r, column_count = 0;
|
||||||
|
@ -521,33 +579,169 @@ static UINT table_get_column_info( MSIDATABASE *db, LPCWSTR name, MSICOLUMNINFO
|
||||||
/* get the number of columns in this table */
|
/* get the number of columns in this table */
|
||||||
column_count = 0;
|
column_count = 0;
|
||||||
r = get_tablecolumns( db, name, NULL, &column_count );
|
r = get_tablecolumns( db, name, NULL, &column_count );
|
||||||
if( r != ERROR_SUCCESS )
|
if (r != ERROR_SUCCESS)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
*pcount = column_count;
|
*pcount = column_count;
|
||||||
|
|
||||||
/* if there's no columns, there's no table */
|
/* if there's no columns, there's no table */
|
||||||
if( column_count == 0 )
|
if (!column_count)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
TRACE("Table %s found\n", debugstr_w(name) );
|
TRACE("table %s found\n", debugstr_w(name));
|
||||||
|
|
||||||
columns = msi_alloc( column_count*sizeof (MSICOLUMNINFO) );
|
columns = msi_alloc( column_count * sizeof(MSICOLUMNINFO) );
|
||||||
if( !columns )
|
if (!columns)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
r = get_tablecolumns( db, name, columns, &column_count );
|
r = get_tablecolumns( db, name, columns, &column_count );
|
||||||
if( r != ERROR_SUCCESS )
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
msi_free( columns );
|
msi_free( columns );
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pcols = columns;
|
*pcols = columns;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
|
||||||
|
{
|
||||||
|
MSITABLE *table;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
/* first, see if the table is cached */
|
||||||
|
table = find_cached_table( db, name );
|
||||||
|
if (table)
|
||||||
|
{
|
||||||
|
*table_ret = table;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nonexistent tables should be interpreted as empty tables */
|
||||||
|
table = msi_alloc( sizeof(MSITABLE) + lstrlenW( name ) * sizeof(WCHAR) );
|
||||||
|
if (!table)
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
table->row_count = 0;
|
||||||
|
table->data = NULL;
|
||||||
|
table->data_persistent = NULL;
|
||||||
|
table->colinfo = NULL;
|
||||||
|
table->col_count = 0;
|
||||||
|
table->persistent = MSICONDITION_TRUE;
|
||||||
|
lstrcpyW( table->name, name );
|
||||||
|
|
||||||
|
if (!strcmpW( name, szTables ) || !strcmpW( name, szColumns ))
|
||||||
|
table->persistent = MSICONDITION_NONE;
|
||||||
|
|
||||||
|
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( db, table, db->storage );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
free_table( table );
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
list_add_head( &db->tables, &table->entry );
|
||||||
|
*table_ret = table;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT read_table_int( BYTE *const *data, UINT row, UINT col, UINT bytes )
|
||||||
|
{
|
||||||
|
UINT ret = 0, i;
|
||||||
|
|
||||||
|
for (i = 0; i < bytes; i++)
|
||||||
|
ret += data[row][col + i] << i * 8;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LPWSTR msi_makestring( const MSIDATABASE *db, UINT string_id )
|
||||||
|
{
|
||||||
|
return strdupW( msi_string_lookup_id( db->strings, string_id ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT get_tablecolumns( MSIDATABASE *db, LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz )
|
||||||
|
{
|
||||||
|
UINT r, i, n = 0, table_id, count, maxcount = *sz;
|
||||||
|
MSITABLE *table = NULL;
|
||||||
|
|
||||||
|
TRACE("%s\n", debugstr_w(szTableName));
|
||||||
|
|
||||||
|
/* first check if there is a default table with that name */
|
||||||
|
r = get_defaulttablecolumns( db, szTableName, colinfo, sz );
|
||||||
|
if (r == ERROR_SUCCESS && *sz)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = get_table( db, szColumns, &table );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("couldn't load _Columns table\n");
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert table and column names to IDs from the string table */
|
||||||
|
r = msi_string2idW( db->strings, szTableName, &table_id );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WARN("Couldn't find id for %s\n", debugstr_w(szTableName));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
TRACE("Table id is %d, row count is %d\n", table_id, table->row_count);
|
||||||
|
|
||||||
|
/* Note: _Columns table doesn't have non-persistent data */
|
||||||
|
|
||||||
|
/* if maxcount is non-zero, assume it's exactly right for this table */
|
||||||
|
memset( colinfo, 0, maxcount * sizeof(*colinfo) );
|
||||||
|
count = table->row_count;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (read_table_int( table->data, i, 0, LONG_STR_BYTES) != table_id) continue;
|
||||||
|
if (colinfo)
|
||||||
|
{
|
||||||
|
UINT id = read_table_int( table->data, i, table->colinfo[2].offset, LONG_STR_BYTES );
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ERR("column %d out of range\n", col);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* check if this column was already set */
|
||||||
|
if (colinfo[col - 1].number)
|
||||||
|
{
|
||||||
|
ERR("duplicate column %d\n", col);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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, 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;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
TRACE("%s has %d columns\n", debugstr_w(szTableName), n);
|
||||||
|
|
||||||
|
if (colinfo && n != maxcount)
|
||||||
|
{
|
||||||
|
ERR("missing column in table %s\n", debugstr_w(szTableName));
|
||||||
|
msi_free_colinfo( colinfo, maxcount );
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
table_calc_column_offsets( db, colinfo, n );
|
||||||
|
*sz = n;
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
||||||
MSICONDITION persistent, MSITABLE **table_ret)
|
MSICONDITION persistent, MSITABLE **table_ret)
|
||||||
{
|
{
|
||||||
|
@ -700,64 +894,6 @@ err:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT get_table( MSIDATABASE *db, LPCWSTR name, MSITABLE **table_ret )
|
|
||||||
{
|
|
||||||
MSITABLE *table;
|
|
||||||
UINT r;
|
|
||||||
|
|
||||||
/* first, see if the table is cached */
|
|
||||||
table = find_cached_table( db, name );
|
|
||||||
if( table )
|
|
||||||
{
|
|
||||||
*table_ret = table;
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nonexistent tables should be interpreted as empty tables */
|
|
||||||
table = msi_alloc( sizeof (MSITABLE) + lstrlenW(name)*sizeof (WCHAR) );
|
|
||||||
if( !table )
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
|
|
||||||
table->row_count = 0;
|
|
||||||
table->data = NULL;
|
|
||||||
table->data_persistent = NULL;
|
|
||||||
table->colinfo = NULL;
|
|
||||||
table->col_count = 0;
|
|
||||||
table->persistent = MSICONDITION_TRUE;
|
|
||||||
lstrcpyW( table->name, name );
|
|
||||||
|
|
||||||
if ( !strcmpW( name, szTables ) || !strcmpW( name, szColumns ) )
|
|
||||||
table->persistent = MSICONDITION_NONE;
|
|
||||||
|
|
||||||
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( db, table, db->storage );
|
|
||||||
if( r != ERROR_SUCCESS )
|
|
||||||
{
|
|
||||||
free_table( table );
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_add_head( &db->tables, &table->entry );
|
|
||||||
*table_ret = table;
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT read_table_int(BYTE *const *data, UINT row, UINT col, UINT bytes)
|
|
||||||
{
|
|
||||||
UINT ret = 0, i;
|
|
||||||
|
|
||||||
for (i = 0; i < bytes; i++)
|
|
||||||
ret += data[row][col + i] << i * 8;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT save_table( MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref )
|
static UINT save_table( MSIDATABASE *db, const MSITABLE *t, UINT bytes_per_strref )
|
||||||
{
|
{
|
||||||
BYTE *rawdata = NULL;
|
BYTE *rawdata = NULL;
|
||||||
|
@ -833,165 +969,6 @@ err:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void table_calc_column_offsets( MSIDATABASE *db, MSICOLUMNINFO *colinfo, DWORD count )
|
|
||||||
{
|
|
||||||
DWORD i;
|
|
||||||
|
|
||||||
for( i=0; colinfo && (i<count); i++ )
|
|
||||||
{
|
|
||||||
assert( (i+1) == colinfo[ i ].number );
|
|
||||||
if (i)
|
|
||||||
colinfo[i].offset = colinfo[ i - 1 ].offset
|
|
||||||
+ bytes_per_column( db, &colinfo[ i - 1 ], LONG_STR_BYTES );
|
|
||||||
else
|
|
||||||
colinfo[i].offset = 0;
|
|
||||||
TRACE("column %d is [%s] with type %08x ofs %d\n",
|
|
||||||
colinfo[i].number, debugstr_w(colinfo[i].colname),
|
|
||||||
colinfo[i].type, colinfo[i].offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT get_defaulttablecolumns( MSIDATABASE *db, LPCWSTR name,
|
|
||||||
MSICOLUMNINFO *colinfo, UINT *sz)
|
|
||||||
{
|
|
||||||
const MSICOLUMNINFO *p;
|
|
||||||
DWORD i, n;
|
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_w(name));
|
|
||||||
|
|
||||||
if (!strcmpW( name, szTables ))
|
|
||||||
{
|
|
||||||
p = _Tables_cols;
|
|
||||||
n = 1;
|
|
||||||
}
|
|
||||||
else if (!strcmpW( name, szColumns ))
|
|
||||||
{
|
|
||||||
p = _Columns_cols;
|
|
||||||
n = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
|
|
||||||
/* duplicate the string data so we can free it in msi_free_colinfo */
|
|
||||||
for (i=0; i<n; i++)
|
|
||||||
{
|
|
||||||
if (colinfo && (i < *sz) )
|
|
||||||
{
|
|
||||||
colinfo[i] = p[i];
|
|
||||||
colinfo[i].tablename = strdupW( p[i].tablename );
|
|
||||||
colinfo[i].colname = strdupW( p[i].colname );
|
|
||||||
}
|
|
||||||
if( colinfo && (i >= *sz) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
table_calc_column_offsets( db, colinfo, n );
|
|
||||||
*sz = n;
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count )
|
|
||||||
{
|
|
||||||
UINT i;
|
|
||||||
|
|
||||||
for( i=0; i<count; i++ )
|
|
||||||
{
|
|
||||||
msi_free( colinfo[i].tablename );
|
|
||||||
msi_free( colinfo[i].colname );
|
|
||||||
msi_free( colinfo[i].hash_table );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static LPWSTR msi_makestring( const MSIDATABASE *db, UINT stringid)
|
|
||||||
{
|
|
||||||
return strdupW(msi_string_lookup_id( db->strings, stringid ));
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT get_tablecolumns( MSIDATABASE *db,
|
|
||||||
LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz)
|
|
||||||
{
|
|
||||||
UINT r, i, n=0, table_id, count, maxcount = *sz;
|
|
||||||
MSITABLE *table = NULL;
|
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_w(szTableName));
|
|
||||||
|
|
||||||
/* first check if there is a default table with that name */
|
|
||||||
r = get_defaulttablecolumns( db, szTableName, colinfo, sz );
|
|
||||||
if( ( r == ERROR_SUCCESS ) && *sz )
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = get_table( db, szColumns, &table );
|
|
||||||
if( r != ERROR_SUCCESS )
|
|
||||||
{
|
|
||||||
ERR("couldn't load _Columns table\n");
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert table and column names to IDs from the string table */
|
|
||||||
r = msi_string2idW( db->strings, szTableName, &table_id );
|
|
||||||
if( r != ERROR_SUCCESS )
|
|
||||||
{
|
|
||||||
WARN("Couldn't find id for %s\n", debugstr_w(szTableName));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("Table id is %d, row count is %d\n", table_id, table->row_count);
|
|
||||||
|
|
||||||
/* Note: _Columns table doesn't have non-persistent data */
|
|
||||||
|
|
||||||
/* if maxcount is non-zero, assume it's exactly right for this table */
|
|
||||||
memset( colinfo, 0, maxcount*sizeof(*colinfo) );
|
|
||||||
count = table->row_count;
|
|
||||||
for( i=0; i<count; i++ )
|
|
||||||
{
|
|
||||||
if( read_table_int(table->data, i, 0, LONG_STR_BYTES) != table_id )
|
|
||||||
continue;
|
|
||||||
if( colinfo )
|
|
||||||
{
|
|
||||||
UINT id = read_table_int(table->data, i, table->colinfo[2].offset, LONG_STR_BYTES);
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
ERR("column %d out of range\n", col);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if this column was already set */
|
|
||||||
if (colinfo[ col - 1 ].number)
|
|
||||||
{
|
|
||||||
ERR("duplicate column %d\n", col);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("%s has %d columns\n", debugstr_w(szTableName), n);
|
|
||||||
|
|
||||||
if (colinfo && n != maxcount)
|
|
||||||
{
|
|
||||||
ERR("missing column in table %s\n", debugstr_w(szTableName));
|
|
||||||
msi_free_colinfo(colinfo, maxcount );
|
|
||||||
return ERROR_FUNCTION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
table_calc_column_offsets( db, colinfo, n );
|
|
||||||
*sz = n;
|
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msi_update_table_columns( MSIDATABASE *db, LPCWSTR name )
|
static void msi_update_table_columns( MSIDATABASE *db, LPCWSTR name )
|
||||||
{
|
{
|
||||||
MSITABLE *table;
|
MSITABLE *table;
|
||||||
|
|
Loading…
Reference in New Issue