From 63e03de9c7f093a536b48f999768b861aa5a60d9 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Fri, 15 Mar 2019 10:04:04 +0100 Subject: [PATCH] msidb: Add support for wildcard (full database) export. 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. Signed-off-by: Erich E. Hoover Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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 3916e0d7219..4bd065abe0e 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 */ }