mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Rebase against 05994cd6179626438ef26c13ee45323a6a1f66eb.
This commit is contained in:
parent
65e6bb8111
commit
6c37563f92
@ -1,64 +0,0 @@
|
||||
From 06bd88e4154eb5eb41011a3f51fe7fac05447b41 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Thu, 17 Sep 2015 10:21:27 -0600
|
||||
Subject: msi: Add support for deleting streams from an MSI database.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
dlls/msi/streams.c | 28 ++++++++++++++++++++++++++--
|
||||
1 file changed, 26 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c
|
||||
index 7f9582c..e170c03 100644
|
||||
--- a/dlls/msi/streams.c
|
||||
+++ b/dlls/msi/streams.c
|
||||
@@ -208,7 +208,28 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row
|
||||
|
||||
static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row)
|
||||
{
|
||||
- FIXME("(%p %d): stub!\n", view, row);
|
||||
+ MSIDATABASE *db = ((MSISTREAMSVIEW *)view)->db;
|
||||
+ UINT i, num_rows = db->num_streams - 1;
|
||||
+ const WCHAR *name;
|
||||
+ WCHAR *encname;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ TRACE("(%p %d)!\n", view, row);
|
||||
+
|
||||
+ name = msi_string_lookup( db->strings, db->streams[row].str_index, NULL );
|
||||
+ if (!(encname = encode_streamname( FALSE, name ))) return ERROR_OUTOFMEMORY;
|
||||
+ hr = IStorage_DestroyElement( db->storage, encname );
|
||||
+ msi_free( encname );
|
||||
+ if (FAILED( hr ))
|
||||
+ return ERROR_FUNCTION_FAILED;
|
||||
+ hr = IStream_Release( db->streams[row].stream );
|
||||
+ if (FAILED( hr ))
|
||||
+ return ERROR_FUNCTION_FAILED;
|
||||
+
|
||||
+ for (i = row; i < num_rows; i++)
|
||||
+ db->streams[i] = db->streams[i + 1];
|
||||
+ db->num_streams = num_rows;
|
||||
+
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -307,12 +328,15 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
|
||||
r = streams_modify_update(view, rec);
|
||||
break;
|
||||
|
||||
+ case MSIMODIFY_DELETE:
|
||||
+ r = STREAMS_delete_row(view, row - 1);
|
||||
+ break;
|
||||
+
|
||||
case MSIMODIFY_VALIDATE_NEW:
|
||||
case MSIMODIFY_INSERT_TEMPORARY:
|
||||
case MSIMODIFY_REFRESH:
|
||||
case MSIMODIFY_REPLACE:
|
||||
case MSIMODIFY_MERGE:
|
||||
- case MSIMODIFY_DELETE:
|
||||
case MSIMODIFY_VALIDATE:
|
||||
case MSIMODIFY_VALIDATE_FIELD:
|
||||
case MSIMODIFY_VALIDATE_DELETE:
|
||||
--
|
||||
2.5.1
|
||||
|
@ -1,158 +0,0 @@
|
||||
From 1a79601491aa1a2ccdff262df085a4c025d4e724 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Thu, 17 Sep 2015 10:32:50 -0600
|
||||
Subject: msidb: Add support for removing stream/cabinet files from MSI
|
||||
databases.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
programs/msidb/main.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 70 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/programs/msidb/main.c b/programs/msidb/main.c
|
||||
index b287484..51b289c 100644
|
||||
--- a/programs/msidb/main.c
|
||||
+++ b/programs/msidb/main.c
|
||||
@@ -43,9 +43,11 @@ struct msidb_state
|
||||
WCHAR *table_folder;
|
||||
MSIHANDLE database_handle;
|
||||
BOOL add_streams;
|
||||
+ BOOL kill_streams;
|
||||
BOOL create_database;
|
||||
BOOL import_tables;
|
||||
struct list add_stream_list;
|
||||
+ struct list kill_stream_list;
|
||||
struct list table_list;
|
||||
};
|
||||
|
||||
@@ -85,6 +87,7 @@ static void show_usage( void )
|
||||
" -d package.msi Path to the database file.\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"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -95,19 +98,20 @@ static int valid_state( struct msidb_state *state )
|
||||
FIXME( "GUI operation is not currently supported.\n" );
|
||||
return 0;
|
||||
}
|
||||
- if (state->table_folder == NULL && !state->add_streams)
|
||||
+ if (state->table_folder == NULL && !state->add_streams && !state->kill_streams)
|
||||
{
|
||||
ERR( "No table folder specified (-f option).\n" );
|
||||
show_usage();
|
||||
return 0;
|
||||
}
|
||||
- if (!state->create_database && !state->import_tables && !state->add_streams)
|
||||
+ if (!state->create_database && !state->import_tables && !state->add_streams
|
||||
+ && !state->kill_streams)
|
||||
{
|
||||
- ERR( "No mode flag specified (-a, -c, -i).\n" );
|
||||
+ ERR( "No mode flag specified (-a, -c, -i, -k).\n" );
|
||||
show_usage();
|
||||
return 0;
|
||||
}
|
||||
- if (list_empty( &state->table_list ) && !state->add_streams)
|
||||
+ if (list_empty( &state->table_list ) && !state->add_streams && !state->kill_streams)
|
||||
{
|
||||
ERR( "No tables specified.\n" );
|
||||
return 0;
|
||||
@@ -144,6 +148,11 @@ static int process_argument( struct msidb_state *state, int i, int argc, WCHAR *
|
||||
case 'i':
|
||||
state->import_tables = TRUE;
|
||||
return 1;
|
||||
+ case 'k':
|
||||
+ if (i + 1 >= argc) return 0;
|
||||
+ state->kill_streams = TRUE;
|
||||
+ list_append( &state->kill_stream_list, argv[i + 1] );
|
||||
+ return 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -256,6 +265,59 @@ static int add_streams( struct msidb_state *state )
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int kill_stream( struct msidb_state *state, const WCHAR *stream_filename )
|
||||
+{
|
||||
+ static const char delete_command[] = "DELETE FROM _Streams WHERE Name = ?";
|
||||
+ MSIHANDLE view = 0, record = 0;
|
||||
+ UINT ret;
|
||||
+
|
||||
+ ret = MsiDatabaseOpenViewA( state->database_handle, delete_command, &view );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to open _Streams table.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ record = MsiCreateRecord( 1 );
|
||||
+ if (record == 0)
|
||||
+ {
|
||||
+ ERR( "Failed to create MSI record.\n" );
|
||||
+ ret = ERROR_OUTOFMEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ret = MsiRecordSetStringW( record, 1, stream_filename );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to add stream filename to MSI record.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ret = MsiViewExecute( view, record );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to delete stream from _Streams table.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+cleanup:
|
||||
+ if (record)
|
||||
+ MsiCloseHandle( record );
|
||||
+ if (view)
|
||||
+ MsiViewClose( view );
|
||||
+
|
||||
+ return (ret == ERROR_SUCCESS);
|
||||
+}
|
||||
+
|
||||
+static int kill_streams( struct msidb_state *state )
|
||||
+{
|
||||
+ struct msidb_listentry *data;
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY( data, &state->kill_stream_list, struct msidb_listentry, entry )
|
||||
+ {
|
||||
+ if (!kill_stream( state, data->name ))
|
||||
+ return 0; /* failed, do not commit changes */
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int import_table( struct msidb_state *state, const WCHAR *table_name )
|
||||
{
|
||||
const WCHAR format[] = { '%','.','8','s','.','i','d','t',0 }; /* truncate to 8 characters */
|
||||
@@ -292,6 +354,7 @@ int wmain( int argc, WCHAR *argv[] )
|
||||
|
||||
memset( &state, 0x0, sizeof(state) );
|
||||
list_init( &state.add_stream_list );
|
||||
+ list_init( &state.kill_stream_list );
|
||||
list_init( &state.table_list );
|
||||
/* process and validate all the command line flags */
|
||||
for (i = 1; n && i < argc; i += n)
|
||||
@@ -312,11 +375,14 @@ int wmain( int argc, WCHAR *argv[] )
|
||||
goto cleanup; /* failed, do not commit changes */
|
||||
if (state.import_tables && !import_tables( &state ))
|
||||
goto cleanup; /* failed, do not commit changes */
|
||||
+ if (state.kill_streams && !kill_streams( &state ))
|
||||
+ goto cleanup; /* failed, do not commit changes */
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
close_database( &state, ret == 0 );
|
||||
list_free( &state.add_stream_list );
|
||||
+ list_free( &state.kill_stream_list );
|
||||
list_free( &state.table_list );
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.5.1
|
||||
|
@ -1,199 +0,0 @@
|
||||
From 683cf39b0e8ff7e497900fdd52d84d50bec0b3a2 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Thu, 17 Sep 2015 14:04:17 -0600
|
||||
Subject: msidb: Add support for extracting stream/cabinet files from MSI
|
||||
databases.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
programs/msidb/main.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 107 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/programs/msidb/main.c b/programs/msidb/main.c
|
||||
index 51b289c..ef63665 100644
|
||||
--- a/programs/msidb/main.c
|
||||
+++ b/programs/msidb/main.c
|
||||
@@ -43,10 +43,12 @@ struct msidb_state
|
||||
WCHAR *table_folder;
|
||||
MSIHANDLE database_handle;
|
||||
BOOL add_streams;
|
||||
+ BOOL extract_streams;
|
||||
BOOL kill_streams;
|
||||
BOOL create_database;
|
||||
BOOL import_tables;
|
||||
struct list add_stream_list;
|
||||
+ struct list extract_stream_list;
|
||||
struct list kill_stream_list;
|
||||
struct list table_list;
|
||||
};
|
||||
@@ -88,6 +90,7 @@ static void show_usage( void )
|
||||
" -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"
|
||||
+ " -x file.cab Extract stream/cabinet file from _Streams table.\n"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,20 +101,22 @@ static int valid_state( struct msidb_state *state )
|
||||
FIXME( "GUI operation is not currently supported.\n" );
|
||||
return 0;
|
||||
}
|
||||
- if (state->table_folder == NULL && !state->add_streams && !state->kill_streams)
|
||||
+ if (state->table_folder == NULL && !state->add_streams && !state->kill_streams
|
||||
+ && !state->extract_streams)
|
||||
{
|
||||
ERR( "No table folder specified (-f option).\n" );
|
||||
show_usage();
|
||||
return 0;
|
||||
}
|
||||
if (!state->create_database && !state->import_tables && !state->add_streams
|
||||
- && !state->kill_streams)
|
||||
+ && !state->kill_streams && !state->extract_streams)
|
||||
{
|
||||
- ERR( "No mode flag specified (-a, -c, -i, -k).\n" );
|
||||
+ ERR( "No mode flag specified (-a, -c, -i, -k, -x).\n" );
|
||||
show_usage();
|
||||
return 0;
|
||||
}
|
||||
- if (list_empty( &state->table_list ) && !state->add_streams && !state->kill_streams)
|
||||
+ if (list_empty( &state->table_list ) && !state->add_streams && !state->kill_streams
|
||||
+ && !state->extract_streams)
|
||||
{
|
||||
ERR( "No tables specified.\n" );
|
||||
return 0;
|
||||
@@ -153,6 +158,11 @@ static int process_argument( struct msidb_state *state, int i, int argc, WCHAR *
|
||||
state->kill_streams = TRUE;
|
||||
list_append( &state->kill_stream_list, argv[i + 1] );
|
||||
return 2;
|
||||
+ case 'x':
|
||||
+ if (i + 1 >= argc) return 0;
|
||||
+ state->extract_streams = TRUE;
|
||||
+ list_append( &state->extract_stream_list, argv[i + 1] );
|
||||
+ return 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -318,6 +328,95 @@ static int kill_streams( struct msidb_state *state )
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int extract_stream( struct msidb_state *state, const WCHAR *stream_filename )
|
||||
+{
|
||||
+ static const char select_command[] = "SELECT Data FROM _Streams WHERE Name = ?";
|
||||
+ HANDLE file = INVALID_HANDLE_VALUE;
|
||||
+ MSIHANDLE view = 0, record = 0;
|
||||
+ DWORD read_size, write_size;
|
||||
+ char buffer[1024];
|
||||
+ UINT ret;
|
||||
+
|
||||
+ file = CreateFileW( stream_filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
+ NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
+ if (file == INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ ret = ERROR_FILE_NOT_FOUND;
|
||||
+ ERR( "Failed to open destination file %s.\n", wine_dbgstr_w(stream_filename) );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ret = MsiDatabaseOpenViewA( state->database_handle, select_command, &view );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to open _Streams table.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ record = MsiCreateRecord( 1 );
|
||||
+ if (record == 0)
|
||||
+ {
|
||||
+ ERR( "Failed to create MSI record.\n" );
|
||||
+ ret = ERROR_OUTOFMEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ret = MsiRecordSetStringW( record, 1, stream_filename );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to add stream filename to MSI record.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ret = MsiViewExecute( view, record );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to query stream from _Streams table.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ MsiCloseHandle( record );
|
||||
+ record = 0;
|
||||
+ ret = MsiViewFetch( view, &record );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to query row from _Streams table.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ read_size = sizeof(buffer);
|
||||
+ while (read_size == sizeof(buffer))
|
||||
+ {
|
||||
+ ret = MsiRecordReadStream( record, 1, buffer, &read_size );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to read stream from _Streams table.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
|
||||
+ {
|
||||
+ ret = ERROR_WRITE_FAULT;
|
||||
+ ERR( "Failed to write stream to destination file.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+cleanup:
|
||||
+ if (record)
|
||||
+ MsiCloseHandle( record );
|
||||
+ if (view)
|
||||
+ MsiViewClose( view );
|
||||
+ if (file != INVALID_HANDLE_VALUE)
|
||||
+ CloseHandle( file );
|
||||
+ return (ret == ERROR_SUCCESS);
|
||||
+}
|
||||
+
|
||||
+static int extract_streams( struct msidb_state *state )
|
||||
+{
|
||||
+ struct msidb_listentry *data;
|
||||
+
|
||||
+ LIST_FOR_EACH_ENTRY( data, &state->extract_stream_list, struct msidb_listentry, entry )
|
||||
+ {
|
||||
+ if (!extract_stream( state, data->name ))
|
||||
+ return 0; /* failed, do not commit changes */
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int import_table( struct msidb_state *state, const WCHAR *table_name )
|
||||
{
|
||||
const WCHAR format[] = { '%','.','8','s','.','i','d','t',0 }; /* truncate to 8 characters */
|
||||
@@ -354,6 +453,7 @@ int wmain( int argc, WCHAR *argv[] )
|
||||
|
||||
memset( &state, 0x0, sizeof(state) );
|
||||
list_init( &state.add_stream_list );
|
||||
+ list_init( &state.extract_stream_list );
|
||||
list_init( &state.kill_stream_list );
|
||||
list_init( &state.table_list );
|
||||
/* process and validate all the command line flags */
|
||||
@@ -373,6 +473,8 @@ int wmain( int argc, WCHAR *argv[] )
|
||||
}
|
||||
if (state.add_streams && !add_streams( &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 ))
|
||||
goto cleanup; /* failed, do not commit changes */
|
||||
if (state.kill_streams && !kill_streams( &state ))
|
||||
@@ -382,6 +484,7 @@ int wmain( int argc, WCHAR *argv[] )
|
||||
cleanup:
|
||||
close_database( &state, ret == 0 );
|
||||
list_free( &state.add_stream_list );
|
||||
+ list_free( &state.extract_stream_list );
|
||||
list_free( &state.kill_stream_list );
|
||||
list_free( &state.table_list );
|
||||
return ret;
|
||||
--
|
||||
2.5.1
|
||||
|
@ -1,101 +0,0 @@
|
||||
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
|
||||
|
@ -1,54 +0,0 @@
|
||||
From 767e70ef58c963eef742ee95b64c4c488035c3e7 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Thu, 17 Sep 2015 15:09:24 -0600
|
||||
Subject: msidb: Add support for exporting with short (DOS) filenames.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
programs/msidb/main.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/programs/msidb/main.c b/programs/msidb/main.c
|
||||
index 7eb6d8b..49dd11b 100644
|
||||
--- a/programs/msidb/main.c
|
||||
+++ b/programs/msidb/main.c
|
||||
@@ -48,6 +48,7 @@ struct msidb_state
|
||||
BOOL create_database;
|
||||
BOOL import_tables;
|
||||
BOOL export_tables;
|
||||
+ BOOL short_filenames;
|
||||
struct list add_stream_list;
|
||||
struct list extract_stream_list;
|
||||
struct list kill_stream_list;
|
||||
@@ -92,6 +93,7 @@ static void show_usage( void )
|
||||
" -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"
|
||||
+ " -s Export with short filenames (eight character max).\n"
|
||||
" -x file.cab Extract stream/cabinet file from _Streams table.\n"
|
||||
);
|
||||
}
|
||||
@@ -163,6 +165,9 @@ static int process_argument( struct msidb_state *state, int i, int argc, WCHAR *
|
||||
state->kill_streams = TRUE;
|
||||
list_append( &state->kill_stream_list, argv[i + 1] );
|
||||
return 2;
|
||||
+ case 's':
|
||||
+ state->short_filenames = TRUE;
|
||||
+ return 1;
|
||||
case 'x':
|
||||
if (i + 1 >= argc) return 0;
|
||||
state->extract_streams = TRUE;
|
||||
@@ -452,7 +457,9 @@ static int import_tables( struct msidb_state *state )
|
||||
|
||||
static int export_table( struct msidb_state *state, const WCHAR *table_name )
|
||||
{
|
||||
- const WCHAR format[] = { '%','s','.','i','d','t',0 };
|
||||
+ const WCHAR format_dos[] = { '%','.','8','s','.','i','d','t',0 }; /* truncate to 8 characters */
|
||||
+ const WCHAR format_full[] = { '%','s','.','i','d','t',0 };
|
||||
+ const WCHAR *format = (state->short_filenames ? format_dos : format_full);
|
||||
WCHAR table_path[MAX_PATH];
|
||||
UINT ret;
|
||||
|
||||
--
|
||||
2.5.1
|
||||
|
@ -1,200 +0,0 @@
|
||||
From 6a34fd5dad4f8cd722eb07f8e253525544705d0c Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Thu, 17 Sep 2015 17:56:15 -0600
|
||||
Subject: msi: Add support for exporting the _SummaryInformation table.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
dlls/msi/database.c | 22 +++++++++++
|
||||
dlls/msi/msipriv.h | 1 +
|
||||
dlls/msi/suminfo.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 135 insertions(+)
|
||||
|
||||
diff --git a/dlls/msi/database.c b/dlls/msi/database.c
|
||||
index e28cf1c..13eac2a 100644
|
||||
--- a/dlls/msi/database.c
|
||||
+++ b/dlls/msi/database.c
|
||||
@@ -987,9 +987,25 @@ static UINT msi_export_forcecodepage( HANDLE handle, UINT codepage )
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
+static UINT msi_export_summaryinformation( MSIDATABASE *db, HANDLE handle )
|
||||
+{
|
||||
+ static const char header[] = "PropertyId\tValue\r\n"
|
||||
+ "i2\tl255\r\n"
|
||||
+ "_SummaryInformation\tPropertyId\r\n";
|
||||
+ DWORD sz;
|
||||
+
|
||||
+ sz = lstrlenA(header);
|
||||
+ if (!WriteFile(handle, header, sz, &sz, NULL))
|
||||
+ return ERROR_WRITE_FAULT;
|
||||
+
|
||||
+ return msi_export_suminfo( db, handle );
|
||||
+}
|
||||
+
|
||||
static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||
LPCWSTR folder, LPCWSTR file )
|
||||
{
|
||||
+ static const WCHAR summaryinformation[] = {
|
||||
+ '_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0 };
|
||||
static const WCHAR query[] = {
|
||||
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
|
||||
static const WCHAR forcecodepage[] = {
|
||||
@@ -1028,6 +1044,12 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ if (!strcmpW( table, summaryinformation ))
|
||||
+ {
|
||||
+ r = msi_export_summaryinformation( db, handle );
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
r = MSI_OpenQuery( db, &view, query, table );
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
|
||||
index 8e7b592..3aac2af 100644
|
||||
--- a/dlls/msi/msipriv.h
|
||||
+++ b/dlls/msi/msipriv.h
|
||||
@@ -954,6 +954,7 @@ extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty ) DECL
|
||||
extern INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
|
||||
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns ) DECLSPEC_HIDDEN;
|
||||
+extern UINT msi_export_suminfo( MSIDATABASE *db, HANDLE handle ) DECLSPEC_HIDDEN;
|
||||
extern UINT msi_load_suminfo_properties( MSIPACKAGE *package ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* undocumented functions */
|
||||
diff --git a/dlls/msi/suminfo.c b/dlls/msi/suminfo.c
|
||||
index 451fd16b..c929fa5 100644
|
||||
--- a/dlls/msi/suminfo.c
|
||||
+++ b/dlls/msi/suminfo.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
|
||||
+#include "stdio.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winreg.h"
|
||||
@@ -1015,6 +1016,117 @@ end:
|
||||
return r;
|
||||
}
|
||||
|
||||
+static UINT save_prop( MSISUMMARYINFO *si, HANDLE handle, UINT row )
|
||||
+{
|
||||
+ static const char fmt_systemtime[] = "%d/%02d/%02d %02d:%02d:%02d";
|
||||
+ char data[20]; /* largest string: YYYY/MM/DD hh:mm:ss */
|
||||
+ static const char fmt_begin[] = "%u\t";
|
||||
+ static const char data_end[] = "\r\n";
|
||||
+ static const char fmt_int[] = "%u";
|
||||
+ UINT r, data_type, len;
|
||||
+ SYSTEMTIME system_time;
|
||||
+ FILETIME file_time;
|
||||
+ INT int_value;
|
||||
+ awstring str;
|
||||
+ DWORD sz;
|
||||
+
|
||||
+ str.unicode = FALSE;
|
||||
+ str.str.a = NULL;
|
||||
+ len = 0;
|
||||
+ r = get_prop( si, row, &data_type, &int_value, &file_time, &str, &len );
|
||||
+ if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
|
||||
+ return r;
|
||||
+ if (data_type == VT_EMPTY)
|
||||
+ return ERROR_SUCCESS; /* property not set */
|
||||
+ snprintf( data, sizeof(data), fmt_begin, row );
|
||||
+ sz = lstrlenA( data );
|
||||
+ if (!WriteFile( handle, data, sz, &sz, NULL ))
|
||||
+ return ERROR_WRITE_FAULT;
|
||||
+
|
||||
+ switch (data_type)
|
||||
+ {
|
||||
+ case VT_I2:
|
||||
+ case VT_I4:
|
||||
+ snprintf( data, sizeof(data), fmt_int, int_value );
|
||||
+ sz = lstrlenA( data );
|
||||
+ if (!WriteFile( handle, data, sz, &sz, NULL ))
|
||||
+ return ERROR_WRITE_FAULT;
|
||||
+ break;
|
||||
+ case VT_LPSTR:
|
||||
+ len++;
|
||||
+ if (!(str.str.a = msi_alloc( len )))
|
||||
+ return ERROR_OUTOFMEMORY;
|
||||
+ r = get_prop( si, row, NULL, NULL, NULL, &str, &len );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ msi_free( str.str.a );
|
||||
+ return r;
|
||||
+ }
|
||||
+ sz = lstrlenA( str.str.a );
|
||||
+ if (!WriteFile( handle, str.str.a, sz, &sz, NULL ))
|
||||
+ {
|
||||
+ msi_free( str.str.a );
|
||||
+ return ERROR_WRITE_FAULT;
|
||||
+ }
|
||||
+ msi_free( str.str.a );
|
||||
+ break;
|
||||
+ case VT_FILETIME:
|
||||
+ if (!FileTimeToSystemTime( &file_time, &system_time ))
|
||||
+ return ERROR_FUNCTION_FAILED;
|
||||
+ snprintf( data, sizeof(data), fmt_systemtime, system_time.wYear, system_time.wMonth,
|
||||
+ system_time.wDay, system_time.wHour, system_time.wMinute,
|
||||
+ system_time.wSecond );
|
||||
+ sz = lstrlenA( data );
|
||||
+ if (!WriteFile( handle, data, sz, &sz, NULL ))
|
||||
+ return ERROR_WRITE_FAULT;
|
||||
+ break;
|
||||
+ case VT_EMPTY:
|
||||
+ /* cannot reach here, property not set */
|
||||
+ break;
|
||||
+ default:
|
||||
+ FIXME( "Unknown property variant type\n" );
|
||||
+ return ERROR_FUNCTION_FAILED;
|
||||
+ }
|
||||
+
|
||||
+ sz = lstrlenA( data_end );
|
||||
+ if (!WriteFile( handle, data_end, sz, &sz, NULL ))
|
||||
+ return ERROR_WRITE_FAULT;
|
||||
+
|
||||
+ return ERROR_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+UINT msi_export_suminfo( MSIDATABASE *db, HANDLE handle )
|
||||
+{
|
||||
+ UINT i, r, num_rows;
|
||||
+ MSISUMMARYINFO *si;
|
||||
+
|
||||
+ r = msi_get_suminfo( db->storage, 0, &si );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ r = msi_get_db_suminfo( db, 0, &si );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ return r;
|
||||
+
|
||||
+ num_rows = get_property_count( si->property );
|
||||
+ if (!num_rows)
|
||||
+ {
|
||||
+ msiobj_release( &si->hdr );
|
||||
+ return ERROR_FUNCTION_FAILED;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < num_rows; i++)
|
||||
+ {
|
||||
+ r = save_prop( si, handle, i );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ msiobj_release( &si->hdr );
|
||||
+ return r;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ msiobj_release( &si->hdr );
|
||||
+ return ERROR_SUCCESS;
|
||||
+}
|
||||
+
|
||||
UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
|
||||
{
|
||||
MSISUMMARYINFO *si;
|
||||
--
|
||||
2.9.0
|
||||
|
@ -1,113 +0,0 @@
|
||||
From 95dff4faee45b610f212b57cf526bee256b7b4ff Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Fri, 18 Sep 2015 10:15:20 -0600
|
||||
Subject: msi: Break out field exporting into a separate routine.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
dlls/msi/database.c | 73 +++++++++++++++++++++++++++++++++--------------------
|
||||
1 file changed, 45 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/dlls/msi/database.c b/dlls/msi/database.c
|
||||
index 13eac2a..7c511c9 100644
|
||||
--- a/dlls/msi/database.c
|
||||
+++ b/dlls/msi/database.c
|
||||
@@ -920,50 +920,67 @@ end:
|
||||
return r;
|
||||
}
|
||||
|
||||
-static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
|
||||
+static UINT msi_export_field( HANDLE handle, MSIRECORD *row, UINT field )
|
||||
{
|
||||
- UINT i, count, len, r = ERROR_SUCCESS;
|
||||
- const char *sep;
|
||||
char *buffer;
|
||||
+ BOOL bret;
|
||||
DWORD sz;
|
||||
+ UINT r;
|
||||
|
||||
- len = 0x100;
|
||||
- buffer = msi_alloc( len );
|
||||
- if ( !buffer )
|
||||
+ sz = 0x100;
|
||||
+ buffer = msi_alloc( sz );
|
||||
+ if (!buffer)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
- count = MSI_RecordGetFieldCount( row );
|
||||
- for ( i=start; i<=count; i++ )
|
||||
+ r = MSI_RecordGetStringA( row, field, buffer, &sz );
|
||||
+ if (r == ERROR_MORE_DATA)
|
||||
{
|
||||
- sz = len;
|
||||
- r = MSI_RecordGetStringA( row, i, buffer, &sz );
|
||||
- if (r == ERROR_MORE_DATA)
|
||||
+ char *p;
|
||||
+
|
||||
+ sz++; /* leave room for NULL terminator */
|
||||
+ p = msi_realloc( buffer, sz );
|
||||
+ if (!p)
|
||||
{
|
||||
- char *p = msi_realloc( buffer, sz + 1 );
|
||||
- if (!p)
|
||||
- break;
|
||||
- len = sz + 1;
|
||||
- buffer = p;
|
||||
+ msi_free( buffer );
|
||||
+ return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
- sz = len;
|
||||
- r = MSI_RecordGetStringA( row, i, buffer, &sz );
|
||||
- if (r != ERROR_SUCCESS)
|
||||
- break;
|
||||
+ buffer = p;
|
||||
|
||||
- if (!WriteFile( handle, buffer, sz, &sz, NULL ))
|
||||
+ r = MSI_RecordGetStringA( row, field, buffer, &sz );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
{
|
||||
- r = ERROR_FUNCTION_FAILED;
|
||||
- break;
|
||||
+ msi_free( buffer );
|
||||
+ return r;
|
||||
}
|
||||
+ }
|
||||
+ else if (r != ERROR_SUCCESS)
|
||||
+ return r;
|
||||
+
|
||||
+ bret = WriteFile( handle, buffer, sz, &sz, NULL );
|
||||
+ msi_free( buffer );
|
||||
+ if (!bret)
|
||||
+ return ERROR_FUNCTION_FAILED;
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
|
||||
+{
|
||||
+ UINT i, count, r = ERROR_SUCCESS;
|
||||
+ const char *sep;
|
||||
+ DWORD sz;
|
||||
+
|
||||
+ count = MSI_RecordGetFieldCount( row );
|
||||
+ for (i = start; i <= count; i++)
|
||||
+ {
|
||||
+ r = msi_export_field( handle, row, i );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ return r;
|
||||
|
||||
sep = (i < count) ? "\t" : "\r\n";
|
||||
if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
|
||||
- {
|
||||
- r = ERROR_FUNCTION_FAILED;
|
||||
- break;
|
||||
- }
|
||||
+ return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
- msi_free( buffer );
|
||||
return r;
|
||||
}
|
||||
|
||||
--
|
||||
2.5.1
|
||||
|
@ -1,153 +0,0 @@
|
||||
From cde86309c43cf9ebd9ff1e6c12869cdf34ede607 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Fri, 18 Sep 2015 11:07:43 -0600
|
||||
Subject: msi: Add support for exporting binary streams (Binary/Icon tables).
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
dlls/msi/database.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 79 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/msi/database.c b/dlls/msi/database.c
|
||||
index 7c511c9..6627fd0 100644
|
||||
--- a/dlls/msi/database.c
|
||||
+++ b/dlls/msi/database.c
|
||||
@@ -53,6 +53,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0)
|
||||
|
||||
+struct row_export_info
|
||||
+{
|
||||
+ HANDLE handle;
|
||||
+ LPCWSTR folder;
|
||||
+ LPCWSTR table;
|
||||
+};
|
||||
+
|
||||
static void free_transforms( MSIDATABASE *db )
|
||||
{
|
||||
while( !list_empty( &db->transforms ) )
|
||||
@@ -964,8 +971,61 @@ static UINT msi_export_field( HANDLE handle, MSIRECORD *row, UINT field )
|
||||
return r;
|
||||
}
|
||||
|
||||
-static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
|
||||
+static UINT msi_export_stream( LPCWSTR folder, LPCWSTR table, MSIRECORD *row, UINT field,
|
||||
+ UINT start )
|
||||
{
|
||||
+ static const WCHAR fmt_file[] = { '%','s','/','%','s','/','%','s',0 };
|
||||
+ static const WCHAR fmt_folder[] = { '%','s','/','%','s',0 };
|
||||
+ WCHAR stream_name[256], stream_filename[MAX_PATH];
|
||||
+ DWORD sz, read_size, write_size;
|
||||
+ char buffer[1024];
|
||||
+ HANDLE file;
|
||||
+ UINT r;
|
||||
+
|
||||
+ /* get the name of the file */
|
||||
+ sz = sizeof(stream_name)/sizeof(WCHAR);
|
||||
+ r = MSI_RecordGetStringW( row, start, stream_name, &sz );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ return r;
|
||||
+
|
||||
+ /* if the destination folder does not exist then create it (folder name = table name) */
|
||||
+ snprintfW( stream_filename, sizeof(stream_filename)/sizeof(WCHAR), fmt_folder, folder, table );
|
||||
+ if (GetFileAttributesW( stream_filename ) == INVALID_FILE_ATTRIBUTES)
|
||||
+ {
|
||||
+ if (!CreateDirectoryW( stream_filename, NULL ))
|
||||
+ return ERROR_PATH_NOT_FOUND;
|
||||
+ }
|
||||
+
|
||||
+ /* actually create the file */
|
||||
+ snprintfW( stream_filename, sizeof(stream_filename)/sizeof(WCHAR), fmt_file, folder, table, stream_name );
|
||||
+ file = CreateFileW( stream_filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
+ if (file == INVALID_HANDLE_VALUE)
|
||||
+ return ERROR_FILE_NOT_FOUND;
|
||||
+
|
||||
+ /* copy the stream to the file */
|
||||
+ read_size = sizeof(buffer);
|
||||
+ while (read_size == sizeof(buffer))
|
||||
+ {
|
||||
+ r = MSI_RecordReadStream( row, field, buffer, &read_size );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ CloseHandle( file );
|
||||
+ return r;
|
||||
+ }
|
||||
+ if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
|
||||
+ {
|
||||
+ CloseHandle( file );
|
||||
+ return ERROR_WRITE_FAULT;
|
||||
+ }
|
||||
+ }
|
||||
+ CloseHandle( file );
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static UINT msi_export_record( struct row_export_info *row_export_info, MSIRECORD *row, UINT start )
|
||||
+{
|
||||
+ HANDLE handle = row_export_info->handle;
|
||||
UINT i, count, r = ERROR_SUCCESS;
|
||||
const char *sep;
|
||||
DWORD sz;
|
||||
@@ -974,7 +1034,18 @@ static UINT msi_export_record( HANDLE handle, MSIRECORD *row, UINT start )
|
||||
for (i = start; i <= count; i++)
|
||||
{
|
||||
r = msi_export_field( handle, row, i );
|
||||
- if (r != ERROR_SUCCESS)
|
||||
+ if (r == ERROR_INVALID_PARAMETER)
|
||||
+ {
|
||||
+ r = msi_export_stream( row_export_info->folder, row_export_info->table, row, i, start );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ return r;
|
||||
+
|
||||
+ /* exporting a binary stream, repeat the "Name" field */
|
||||
+ r = msi_export_field( handle, row, start );
|
||||
+ if (r != ERROR_SUCCESS)
|
||||
+ return r;
|
||||
+ }
|
||||
+ else if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
sep = (i < count) ? "\t" : "\r\n";
|
||||
@@ -1070,11 +1141,13 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||
r = MSI_OpenQuery( db, &view, query, table );
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
+ struct row_export_info row_export_info = { handle, folder, table };
|
||||
+
|
||||
/* write out row 1, the column names */
|
||||
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
- msi_export_record( handle, rec, 1 );
|
||||
+ msi_export_record( &row_export_info, rec, 1 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
@@ -1082,7 +1155,7 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||
r = MSI_ViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
- msi_export_record( handle, rec, 1 );
|
||||
+ msi_export_record( &row_export_info, rec, 1 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
@@ -1091,12 +1164,12 @@ static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
|
||||
if (r == ERROR_SUCCESS)
|
||||
{
|
||||
MSI_RecordSetStringW( rec, 0, table );
|
||||
- msi_export_record( handle, rec, 0 );
|
||||
+ msi_export_record( &row_export_info, rec, 0 );
|
||||
msiobj_release( &rec->hdr );
|
||||
}
|
||||
|
||||
/* write out row 4 onwards, the data */
|
||||
- r = MSI_IterateRecords( view, 0, msi_export_row, handle );
|
||||
+ r = MSI_IterateRecords( view, 0, msi_export_row, &row_export_info );
|
||||
msiobj_release( &view->hdr );
|
||||
}
|
||||
|
||||
--
|
||||
2.6.2
|
||||
|
@ -1,110 +0,0 @@
|
||||
From 8c0efb4738cddee5545154a87fbdc40300bb5ddc Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
|
||||
Date: Fri, 18 Sep 2015 12:19:19 -0600
|
||||
Subject: msidb: Add support for wildcard (full database) export.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@wine-staging.com>
|
||||
---
|
||||
programs/msidb/main.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 78 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/programs/msidb/main.c b/programs/msidb/main.c
|
||||
index 49dd11b..8796451 100644
|
||||
--- a/programs/msidb/main.c
|
||||
+++ b/programs/msidb/main.c
|
||||
@@ -473,14 +473,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 char query_command[] = "SELECT Name FROM _Tables";
|
||||
+ MSIHANDLE view = 0;
|
||||
+ UINT ret;
|
||||
+
|
||||
+ ret = MsiDatabaseOpenViewA( 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;
|
||||
+ }
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ 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 = sizeof(table)/sizeof(WCHAR);
|
||||
+ ret = MsiRecordGetStringW( record, 1, table, &size );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to retrieve name string.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ ret = MsiCloseHandle( record );
|
||||
+ if (ret != ERROR_SUCCESS)
|
||||
+ {
|
||||
+ ERR( "Failed to close record handle.\n" );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (!export_table( state, table ))
|
||||
+ {
|
||||
+ ret = ERROR_FUNCTION_FAILED;
|
||||
+ 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 );
|
||||
+ 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 (!export_table( state, data->name ))
|
||||
- return 0; /* failed, do not commit changes */
|
||||
+ if (strcmpW( data->name, wildcard ) == 0)
|
||||
+ {
|
||||
+ if (!export_all_tables( state ))
|
||||
+ return 0; /* failed, do not commit changes */
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (!export_table( state, data->name ))
|
||||
+ return 0; /* failed, do not commit changes */
|
||||
+ }
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
--
|
||||
2.5.1
|
||||
|
@ -1 +0,0 @@
|
||||
Fixes: Add implementation for msidb commandline tool
|
@ -1 +1,2 @@
|
||||
Fixes: [46470] opencl: Add support for OpenCL 1.2.
|
||||
Disabled: true
|
||||
|
@ -52,7 +52,7 @@ usage()
|
||||
# Get the upstream commit sha
|
||||
upstream_commit()
|
||||
{
|
||||
echo "fa262317480e52eb3420c4e0ba9bae9e17db4457"
|
||||
echo "05994cd6179626438ef26c13ee45323a6a1f66eb"
|
||||
}
|
||||
|
||||
# Show version information
|
||||
@ -184,7 +184,6 @@ patch_enable_all ()
|
||||
enable_mshtml_HTMLLocation_put_hash="$1"
|
||||
enable_msi_MsiGetDatabaseState="$1"
|
||||
enable_msi_msi_vcl_get_cost="$1"
|
||||
enable_msidb_Implementation="$1"
|
||||
enable_msvcrt_Math_Precision="$1"
|
||||
enable_ntdll_APC_Performance="$1"
|
||||
enable_ntdll_Activation_Context="$1"
|
||||
@ -249,7 +248,6 @@ patch_enable_all ()
|
||||
enable_oleaut32_OLEPictureImpl_SaveAsFile="$1"
|
||||
enable_oleaut32_OleLoadPicture="$1"
|
||||
enable_oleaut32_OleLoadPictureFile="$1"
|
||||
enable_opencl_version_1_2="$1"
|
||||
enable_opengl32_wglChoosePixelFormat="$1"
|
||||
enable_packager_DllMain="$1"
|
||||
enable_pdh_PdhLookupPerfNameByIndex_processor="$1"
|
||||
@ -704,9 +702,6 @@ patch_enable ()
|
||||
msi-msi_vcl_get_cost)
|
||||
enable_msi_msi_vcl_get_cost="$2"
|
||||
;;
|
||||
msidb-Implementation)
|
||||
enable_msidb_Implementation="$2"
|
||||
;;
|
||||
msvcrt-Math_Precision)
|
||||
enable_msvcrt_Math_Precision="$2"
|
||||
;;
|
||||
@ -899,9 +894,6 @@ patch_enable ()
|
||||
oleaut32-OleLoadPictureFile)
|
||||
enable_oleaut32_OleLoadPictureFile="$2"
|
||||
;;
|
||||
opencl-version_1_2)
|
||||
enable_opencl_version_1_2="$2"
|
||||
;;
|
||||
opengl32-wglChoosePixelFormat)
|
||||
enable_opengl32_wglChoosePixelFormat="$2"
|
||||
;;
|
||||
@ -4181,34 +4173,6 @@ if test "$enable_msi_msi_vcl_get_cost" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset msidb-Implementation
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/msi/database.c, dlls/msi/msipriv.h, dlls/msi/streams.c, dlls/msi/suminfo.c, programs/msidb/main.c
|
||||
# |
|
||||
if test "$enable_msidb_Implementation" -eq 1; then
|
||||
patch_apply msidb-Implementation/0005-msi-Add-support-for-deleting-streams-from-an-MSI-dat.patch
|
||||
patch_apply msidb-Implementation/0006-msidb-Add-support-for-removing-stream-cabinet-files-.patch
|
||||
patch_apply msidb-Implementation/0007-msidb-Add-support-for-extracting-stream-cabinet-file.patch
|
||||
patch_apply msidb-Implementation/0008-msidb-Add-support-for-exporting-database-tables.patch
|
||||
patch_apply msidb-Implementation/0009-msidb-Add-support-for-exporting-with-short-DOS-filen.patch
|
||||
patch_apply msidb-Implementation/0010-msi-Add-support-for-exporting-the-_SummaryInformatio.patch
|
||||
patch_apply msidb-Implementation/0011-msi-Break-out-field-exporting-into-a-separate-routin.patch
|
||||
patch_apply msidb-Implementation/0012-msi-Add-support-for-exporting-binary-streams-Binary-.patch
|
||||
patch_apply msidb-Implementation/0013-msidb-Add-support-for-wildcard-full-database-export.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msi: Add support for deleting streams from an MSI database.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msidb: Add support for removing stream/cabinet files from MSI databases.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msidb: Add support for extracting stream/cabinet files from MSI databases.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msidb: Add support for exporting database tables.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msidb: Add support for exporting with short (DOS) filenames.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msi: Add support for exporting the _SummaryInformation table.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msi: Break out field exporting into a separate routine.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msi: Add support for exporting binary streams (Binary/Icon tables).", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "msidb: Add support for wildcard (full database) export.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset msvcrt-Math_Precision
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
@ -5290,29 +5254,6 @@ if test "$enable_oleaut32_OleLoadPictureFile" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset opencl-version_1_2
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#46470] opencl: Add support for OpenCL 1.2.
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * configure, configure.ac, dlls/opencl/opencl.c, dlls/opencl/opencl.spec, include/config.h.in
|
||||
# |
|
||||
if test "$enable_opencl_version_1_2" -eq 1; then
|
||||
patch_apply opencl-version_1_2/0001-opencl-Add-OpenCL-1.0-function-pointer-loader.patch
|
||||
patch_apply opencl-version_1_2/0002-opencl-Use-function-pointer-instead-of-call-the-func.patch
|
||||
patch_apply opencl-version_1_2/0003-opencl-Add-OpenCL-1.1-implementation.patch
|
||||
patch_apply opencl-version_1_2/0004-opencl-Add-OpenCL-1.2-implementation.patch
|
||||
patch_apply opencl-version_1_2/0005-opencl-Expose-all-extensions-list-to-wine.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Nakarin Khankham", "opencl: Add OpenCL 1.0 function pointer loader.", 1 },';
|
||||
printf '%s\n' '+ { "Nakarin Khankham", "opencl: Use function pointer instead of call the function directly.", 1 },';
|
||||
printf '%s\n' '+ { "Nakarin Khankham", "opencl: Add OpenCL 1.1 implementation.", 1 },';
|
||||
printf '%s\n' '+ { "Nakarin Khankham", "opencl: Add OpenCL 1.2 implementation.", 1 },';
|
||||
printf '%s\n' '+ { "Nakarin Khankham", "opencl: Expose all extensions list to wine.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset opengl32-wglChoosePixelFormat
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user