summaryrefslogtreecommitdiffstats
path: root/libmsi
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-12-03 17:28:45 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2012-12-06 20:30:32 +0100
commite7f5c4c31622299638545486f8de58c3bba76cf9 (patch)
treeb352b7c7015a8e706bbc8e3eab31e6e2e1a63cd4 /libmsi
parent345d1015b63135b94969f02144ac2bba48d7506c (diff)
downloadmsitools-e7f5c4c31622299638545486f8de58c3bba76cf9.tar.gz
msitools-e7f5c4c31622299638545486f8de58c3bba76cf9.tar.xz
msitools-e7f5c4c31622299638545486f8de58c3bba76cf9.zip
load all table names on startup
Diffstat (limited to 'libmsi')
-rw-r--r--libmsi/database.c30
-rw-r--r--libmsi/msipriv.h1
-rw-r--r--libmsi/table.c56
3 files changed, 62 insertions, 25 deletions
diff --git a/libmsi/database.c b/libmsi/database.c
index 31419ee..f4ac940 100644
--- a/libmsi/database.c
+++ b/libmsi/database.c
@@ -412,11 +412,14 @@ static void cache_infile_structure( LibmsiDatabase *db )
IStream *stream;
HRESULT hr;
unsigned r, size;
+ WCHAR decname[0x40];
hr = IStorage_EnumElements(db->infile, 0, NULL, 0, &stgenum);
if (FAILED(hr))
return;
+ /* TODO: error handling */
+
while (true)
{
size = 0;
@@ -425,16 +428,25 @@ static void cache_infile_structure( LibmsiDatabase *db )
break;
/* table streams are not in the _Streams table */
- if (stat.type == STGTY_STREAM && *stat.pwcsName == 0x4840)
- {
- CoTaskMemFree(stat.pwcsName);
- continue;
- }
-
if (stat.type == STGTY_STREAM) {
- r = msi_get_raw_stream(db, stat.pwcsName, &stream);
- if ( r == 0 ) {
- IStream_Release(stream);
+ if (*stat.pwcsName == 0x4840)
+ {
+ decode_streamname( stat.pwcsName + 1, decname );
+ if ( !strcmpW( decname, szStringPool ) ||
+ !strcmpW( decname, szStringData ) )
+ {
+ CoTaskMemFree(stat.pwcsName);
+ continue;
+ }
+
+ r = _libmsi_open_table( db, decname, false );
+ }
+ else
+ {
+ r = msi_get_raw_stream(db, stat.pwcsName, &stream);
+ if ( r == 0 ) {
+ IStream_Release(stream);
+ }
}
} else {
msi_open_storage(db, stat.pwcsName);
diff --git a/libmsi/msipriv.h b/libmsi/msipriv.h
index 653a694..9b91585 100644
--- a/libmsi/msipriv.h
+++ b/libmsi/msipriv.h
@@ -313,6 +313,7 @@ extern unsigned msi_save_string_table( const string_table *st, LibmsiDatabase *d
extern unsigned msi_get_string_table_codepage( const string_table *st );
extern unsigned msi_set_string_table_codepage( string_table *st, unsigned codepage );
+unsigned _libmsi_open_table( LibmsiDatabase *db, const WCHAR *name, bool encoded );
extern bool table_view_exists( LibmsiDatabase *db, const WCHAR *name );
extern LibmsiCondition _libmsi_database_is_table_persistent( LibmsiDatabase *db, const WCHAR *table );
diff --git a/libmsi/table.c b/libmsi/table.c
index df350da..bf3823a 100644
--- a/libmsi/table.c
+++ b/libmsi/table.c
@@ -625,48 +625,69 @@ static unsigned table_get_column_info( LibmsiDatabase *db, const WCHAR *name, Li
return r;
}
-static unsigned get_table( LibmsiDatabase *db, const WCHAR *name, LibmsiTable **table_ret )
+unsigned _libmsi_open_table( LibmsiDatabase *db, const WCHAR *name, bool encoded )
{
+ WCHAR decname[0x40];
LibmsiTable *table;
- unsigned r;
- /* first, see if the table is cached */
- table = find_cached_table( db, name );
- if (table)
+ if (encoded)
{
- *table_ret = table;
- return LIBMSI_RESULT_SUCCESS;
+ assert(name[0] == 0x4840);
+ decode_streamname( name + 1, decname );
+ name = decname;
}
- /* nonexistent tables should be interpreted as empty tables */
- table = msi_alloc( sizeof(LibmsiTable) + strlenW( name ) * sizeof(WCHAR) );
+ table = msi_alloc_zero( sizeof(LibmsiTable) + strlenW( name ) * sizeof(WCHAR) );
if (!table)
return LIBMSI_RESULT_FUNCTION_FAILED;
- table->row_count = 0;
- table->data = NULL;
- table->data_persistent = NULL;
- table->colinfo = NULL;
- table->col_count = 0;
table->persistent = LIBMSI_CONDITION_TRUE;
strcpyW( table->name, name );
if (!strcmpW( name, szTables ) || !strcmpW( name, szColumns ))
table->persistent = LIBMSI_CONDITION_NONE;
+ list_add_head( &db->tables, &table->entry );
+ return LIBMSI_RESULT_SUCCESS;
+}
+
+static unsigned get_table( LibmsiDatabase *db, const WCHAR *name, LibmsiTable **table_ret )
+{
+ LibmsiTable *table;
+ unsigned r;
+
+ /* first, see if the table is cached */
+ table = find_cached_table( db, name );
+ if (!table)
+ {
+ /* nonexistent tables should be interpreted as empty tables */
+ r = _libmsi_open_table( db, name, false );
+ if (r)
+ return r;
+
+ table = find_cached_table( db, name );
+ }
+
+ if (table->colinfo)
+ {
+ *table_ret = table;
+ return LIBMSI_RESULT_SUCCESS;
+ }
+
r = table_get_column_info( db, name, &table->colinfo, &table->col_count );
if (r != LIBMSI_RESULT_SUCCESS)
{
+ list_remove(&table->entry);
free_table( table );
return r;
}
r = read_table_from_storage( db, table, db->infile );
if (r != LIBMSI_RESULT_SUCCESS)
{
+ list_remove(&table->entry);
free_table( table );
return r;
}
- list_add_head( &db->tables, &table->entry );
*table_ret = table;
return LIBMSI_RESULT_SUCCESS;
}
@@ -2072,7 +2093,10 @@ unsigned _libmsi_database_commit_tables( LibmsiDatabase *db, unsigned bytes_per_
LIST_FOR_EACH_ENTRY( table, &db->tables, LibmsiTable, entry )
{
- r = save_table( db, table, bytes_per_strref );
+ /* TODO: delete this if, replace with row_count check in save_table */
+ if (table->colinfo) {
+ r = save_table( db, table, bytes_per_strref );
+ }
if( r != LIBMSI_RESULT_SUCCESS )
{
WARN("failed to save table %s (r=%08x)\n",