From: "Erich E. Hoover" erich.e.hoover@gmail.com
msidb allows a full database export with the special "*" database name. Note: It does not support true wildcards, just this special indication that you wish to export all the tables in the database.
v2: Use Unicode functions, ARRAY_SIZE macro.
Signed-off-by: Erich E. Hoover erich.e.hoover@gmail.com Signed-off-by: Hans Leidekker hans@codeweavers.com --- programs/msidb/main.c | 82 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-)
diff --git a/programs/msidb/main.c b/programs/msidb/main.c index 3916e0d721..4bd065abe0 100644 --- a/programs/msidb/main.c +++ b/programs/msidb/main.c @@ -439,7 +439,7 @@ static int import_table( struct msidb_state *state, const WCHAR *table_name ) WCHAR table_path[MAX_PATH]; UINT ret;
- snprintfW( table_path, sizeof(table_path)/sizeof(WCHAR), format, table_name ); + snprintfW( table_path, ARRAY_SIZE(table_path), format, table_name ); ret = MsiDatabaseImportW( state->database_handle, state->table_folder, table_path ); if (ret != ERROR_SUCCESS) { @@ -469,7 +469,7 @@ static int export_table( struct msidb_state *state, const WCHAR *table_name ) WCHAR table_path[MAX_PATH]; UINT ret;
- snprintfW( table_path, sizeof(table_path)/sizeof(WCHAR), format, table_name ); + snprintfW( table_path, ARRAY_SIZE(table_path), format, table_name ); ret = MsiDatabaseExportW( state->database_handle, table_name, state->table_folder, table_path ); if (ret != ERROR_SUCCESS) { @@ -479,12 +479,90 @@ static int export_table( struct msidb_state *state, const WCHAR *table_name ) return 1; }
+static int export_all_tables( struct msidb_state *state ) +{ + static const WCHAR summary_information[] = + {'_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0}; + static const WCHAR query_command[] = + {'S','E','L','E','C','T',' ','N','a','m','e',' ','F','R','O','M',' ','_','T','a','b','l','e','s',0}; + MSIHANDLE view = 0; + UINT ret; + + ret = MsiDatabaseOpenViewW( state->database_handle, query_command, &view ); + if (ret != ERROR_SUCCESS) + { + ERR( "Failed to open _Tables table.\n" ); + goto cleanup; + } + ret = MsiViewExecute( view, 0 ); + if (ret != ERROR_SUCCESS) + { + ERR( "Failed to query list from _Tables table.\n" ); + goto cleanup; + } + while( 1 ) + { + MSIHANDLE record = 0; + WCHAR table[256]; + DWORD size; + + ret = MsiViewFetch( view, &record ); + if (ret == ERROR_NO_MORE_ITEMS) + break; + if (ret != ERROR_SUCCESS) + { + ERR( "Failed to query row from _Tables table.\n" ); + goto cleanup; + } + size = ARRAY_SIZE(table); + ret = MsiRecordGetStringW( record, 1, table, &size ); + if (ret != ERROR_SUCCESS) + { + ERR( "Failed to retrieve name string.\n" ); + goto cleanup; + } + if (!export_table( state, table )) + { + ret = ERROR_FUNCTION_FAILED; + goto cleanup; + } + ret = MsiCloseHandle( record ); + if (ret != ERROR_SUCCESS) + { + ERR( "Failed to close record handle.\n" ); + goto cleanup; + } + } + ret = ERROR_SUCCESS; + /* the _SummaryInformation table is not listed in _Tables */ + if (!export_table( state, summary_information )) + { + ret = ERROR_FUNCTION_FAILED; + goto cleanup; + } + +cleanup: + if (view && MsiViewClose( view ) != ERROR_SUCCESS) + { + ERR( "Failed to close _Streams table.\n" ); + return 0; + } + return (ret == ERROR_SUCCESS); +} + static int export_tables( struct msidb_state *state ) { + const WCHAR wildcard[] = { '*',0 }; struct msidb_listentry *data;
LIST_FOR_EACH_ENTRY( data, &state->table_list, struct msidb_listentry, entry ) { + if (strcmpW( data->name, wildcard ) == 0) + { + if (!export_all_tables( state )) + return 0; /* failed, do not commit changes */ + continue; + } if (!export_table( state, data->name )) return 0; /* failed, do not commit changes */ }