diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-03 17:28:45 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-06 20:30:32 +0100 |
commit | e7f5c4c31622299638545486f8de58c3bba76cf9 (patch) | |
tree | b352b7c7015a8e706bbc8e3eab31e6e2e1a63cd4 /libmsi | |
parent | 345d1015b63135b94969f02144ac2bba48d7506c (diff) | |
download | msitools-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.c | 30 | ||||
-rw-r--r-- | libmsi/msipriv.h | 1 | ||||
-rw-r--r-- | libmsi/table.c | 56 |
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", |