From fa147d70dd017074fb40361ac4911f09d4c7a8c2 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Thu, 17 Sep 2015 15:04:17 -0600
Subject: msidb: Add support for exporting database tables.

Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
---
 programs/msidb/main.c | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/programs/msidb/main.c b/programs/msidb/main.c
index ef63665..7eb6d8b 100644
--- a/programs/msidb/main.c
+++ b/programs/msidb/main.c
@@ -47,6 +47,7 @@ struct msidb_state
     BOOL kill_streams;
     BOOL create_database;
     BOOL import_tables;
+    BOOL export_tables;
     struct list add_stream_list;
     struct list extract_stream_list;
     struct list kill_stream_list;
@@ -87,6 +88,7 @@ static void show_usage( void )
         "  -a file.cab       Add stream/cabinet file to _Streams table.\n"
         "  -c                Create database file (instead of opening existing file).\n"
         "  -d package.msi    Path to the database file.\n"
+        "  -e                Export tables from database.\n"
         "  -f folder         Folder in which to open/save the tables.\n"
         "  -i                Import tables into database.\n"
         "  -k file.cab       Kill (remove) stream/cabinet file from _Streams table.\n"
@@ -108,10 +110,10 @@ static int valid_state( struct msidb_state *state )
         show_usage();
         return 0;
     }
-    if (!state->create_database && !state->import_tables && !state->add_streams
-        && !state->kill_streams && !state->extract_streams)
+    if (!state->create_database && !state->import_tables && !state->export_tables
+        && !state->add_streams&& !state->kill_streams && !state->extract_streams)
     {
-        ERR( "No mode flag specified (-a, -c, -i, -k, -x).\n" );
+        ERR( "No mode flag specified (-a, -c, -e, -i, -k, -x).\n" );
         show_usage();
         return 0;
     }
@@ -146,6 +148,9 @@ static int process_argument( struct msidb_state *state, int i, int argc, WCHAR *
         if (i + 1 >= argc) return 0;
         state->database_file = argv[i + 1];
         return 2;
+    case 'e':
+        state->export_tables = TRUE;
+        return 1;
     case 'f':
         if (i + 1 >= argc) return 0;
         state->table_folder = argv[i + 1];
@@ -445,6 +450,34 @@ static int import_tables( struct msidb_state *state )
     return 1;
 }
 
+static int export_table( struct msidb_state *state, const WCHAR *table_name )
+{
+    const WCHAR format[] = { '%','s','.','i','d','t',0 };
+    WCHAR table_path[MAX_PATH];
+    UINT ret;
+
+    snprintfW( table_path, sizeof(table_path)/sizeof(WCHAR), format, table_name );
+    ret = MsiDatabaseExportW( state->database_handle, table_name, state->table_folder, table_path );
+    if (ret != ERROR_SUCCESS)
+    {
+        ERR( "Failed to export table '%s', error %d.\n", wine_dbgstr_w(table_name), ret );
+        return 0;
+    }
+    return 1;
+}
+
+static int export_tables( struct msidb_state *state )
+{
+    struct msidb_listentry *data;
+
+    LIST_FOR_EACH_ENTRY( data, &state->table_list, struct msidb_listentry, entry )
+    {
+        if (!export_table( state, data->name ))
+            return 0; /* failed, do not commit changes */
+    }
+    return 1;
+}
+
 int wmain( int argc, WCHAR *argv[] )
 {
     struct msidb_state state;
@@ -473,6 +506,8 @@ int wmain( int argc, WCHAR *argv[] )
     }
     if (state.add_streams && !add_streams( &state ))
         goto cleanup; /* failed, do not commit changes */
+    if (state.export_tables && !export_tables( &state ))
+        goto cleanup; /* failed, do not commit changes */
     if (state.extract_streams && !extract_streams( &state ))
         goto cleanup; /* failed, do not commit changes */
     if (state.import_tables && !import_tables( &state ))
-- 
2.5.1

