[PATCH 9/9] msidb: Add support for wildcard (full database) export.

Hans Leidekker hans at codeweavers.com
Fri Mar 15 04:04:04 CDT 2019


From: "Erich E. Hoover" <erich.e.hoover at 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 at gmail.com>
Signed-off-by: Hans Leidekker <hans at 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 */
     }
-- 
2.20.1




More information about the wine-devel mailing list