Erich E. Hoover : msidb: Add stub tool for manipulating MSI databases.

Alexandre Julliard julliard at winehq.org
Mon Mar 11 16:29:52 CDT 2019


Module: wine
Branch: master
Commit: 3d5b606ddea7ede27eb2320e2755666bdbed1f33
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=3d5b606ddea7ede27eb2320e2755666bdbed1f33

Author: Erich E. Hoover <erich.e.hoover at wine-staging.com>
Date:   Tue Sep 15 17:44:33 2015 -0600

msidb: Add stub tool for manipulating MSI databases.

The "Windows SDK Components for Windows Installer Developers" has a
command line tool called msidb that is incredibly useful for creating,
editing, and exporting MSI installer databases, think of it as
winemsibuilder on steroids.  This patch series implements much of the
functionality of the msidb tool, maintains compatible CLI flags, and
the underlying MSI functionality necessary to support these features.
Jacek expressed an interest in having these patches resurrected for
use by the Gecko build scripts and Austin's VS builds of Valgrind.
With this patch series all the existing winemsibuilder functionality
is available, plus the ability to drop streams, export the
_SummaryInformation table, and export binary streams (Binary/Icon
tables).  A big feature of the implementation is that it allows you to
edit existing installer databases, rather than just creating new ones.

Signed-off-by: Erich E. Hoover <erich.e.hoover at gmail.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 configure                  |   3 +
 configure.ac               |   2 +
 programs/msidb/Makefile.in |   5 ++
 programs/msidb/main.c      | 153 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+)

diff --git a/configure b/configure
index 9988dcd..8a07748 100755
--- a/configure
+++ b/configure
@@ -1715,6 +1715,7 @@ enable_ipconfig
 enable_lodctr
 enable_mofcomp
 enable_mshta
+enable_msidb
 enable_msiexec
 enable_msinfo32
 enable_net
@@ -20292,6 +20293,7 @@ wine_fn_config_makefile programs/ipconfig enable_ipconfig
 wine_fn_config_makefile programs/lodctr enable_lodctr
 wine_fn_config_makefile programs/mofcomp enable_mofcomp
 wine_fn_config_makefile programs/mshta enable_mshta
+wine_fn_config_makefile programs/msidb enable_msidb
 wine_fn_config_makefile programs/msiexec enable_msiexec
 wine_fn_config_makefile programs/msinfo32 enable_msinfo32
 wine_fn_config_makefile programs/net enable_net
@@ -20443,6 +20445,7 @@ else
 fonts \
 loader/l_intl.nls \
 loader/wine.inf \
+programs/msidb/msidb \
 programs/msiexec/msiexec \
 programs/notepad/notepad \
 programs/regedit/regedit \
diff --git a/configure.ac b/configure.ac
index 25581a9..db8bb6c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3938,6 +3938,7 @@ WINE_CONFIG_MAKEFILE(programs/ipconfig)
 WINE_CONFIG_MAKEFILE(programs/lodctr)
 WINE_CONFIG_MAKEFILE(programs/mofcomp)
 WINE_CONFIG_MAKEFILE(programs/mshta)
+WINE_CONFIG_MAKEFILE(programs/msidb)
 WINE_CONFIG_MAKEFILE(programs/msiexec)
 WINE_CONFIG_MAKEFILE(programs/msinfo32)
 WINE_CONFIG_MAKEFILE(programs/net)
@@ -4106,6 +4107,7 @@ else
 fonts \
 loader/l_intl.nls \
 loader/wine.inf \
+programs/msidb/msidb \
 programs/msiexec/msiexec \
 programs/notepad/notepad \
 programs/regedit/regedit \
diff --git a/programs/msidb/Makefile.in b/programs/msidb/Makefile.in
new file mode 100644
index 0000000..bb74041
--- /dev/null
+++ b/programs/msidb/Makefile.in
@@ -0,0 +1,5 @@
+MODULE    = msidb.exe
+APPMODE   = -mconsole -municode
+IMPORTS   = msi
+
+C_SRCS = main.c
diff --git a/programs/msidb/main.c b/programs/msidb/main.c
new file mode 100644
index 0000000..a431fd5
--- /dev/null
+++ b/programs/msidb/main.c
@@ -0,0 +1,153 @@
+/*
+ * msidb - command line tool for assembling MSI packages
+ *
+ * Copyright 2015 Erich E. Hoover
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <stdlib.h>
+#include <windows.h>
+#include <msi.h>
+#include <msiquery.h>
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msidb);
+
+struct msidb_state
+{
+    WCHAR *database_file;
+    WCHAR *table_folder;
+    MSIHANDLE database_handle;
+    BOOL create_database;
+};
+
+static void show_usage( void )
+{
+    WINE_MESSAGE(
+        "Usage: msidb [OPTION]...[OPTION]...\n"
+        "Options:\n"
+        "  -?                Show this usage message and exit.\n"
+        "  -c                Create database file (instead of opening existing file).\n"
+        "  -d package.msi    Path to the database file.\n"
+        "  -f folder         Folder in which to open/save the tables.\n"
+    );
+}
+
+static int valid_state( struct msidb_state *state )
+{
+    if (state->database_file == NULL)
+    {
+        FIXME( "GUI operation is not currently supported.\n" );
+        return 0;
+    }
+    if (state->table_folder == NULL)
+    {
+        ERR( "No table folder specified (-f option).\n" );
+        show_usage();
+        return 0;
+    }
+    return 1;
+}
+
+static int process_argument( struct msidb_state *state, int i, int argc, WCHAR *argv[] )
+{
+    /* msidb accepts either "-" or "/" style flags */
+    if (strlenW(argv[i]) != 2 || (argv[i][0] != '-' && argv[i][0] != '/'))
+    {
+        WINE_FIXME( "Table names are not currently supported.\n" );
+        show_usage();
+        exit( 1 );
+    }
+    switch( argv[i][1] )
+    {
+    case '?':
+        show_usage();
+        exit( 0 );
+    case 'c':
+        state->create_database = TRUE;
+        return 1;
+    case 'd':
+        if (i + 1 >= argc) return 0;
+        state->database_file = argv[i + 1];
+        return 2;
+    case 'f':
+        if (i + 1 >= argc) return 0;
+        state->table_folder = argv[i + 1];
+        return 2;
+    default:
+        break;
+    }
+    show_usage();
+    exit( 1 );
+}
+
+static int open_database( struct msidb_state *state )
+{
+    LPCWSTR db_mode = state->create_database ? MSIDBOPEN_CREATE : MSIDBOPEN_TRANSACT;
+    UINT ret;
+
+    ret = MsiOpenDatabaseW( state->database_file, db_mode, &state->database_handle );
+    if (ret != ERROR_SUCCESS)
+    {
+        ERR( "Failed to open database '%s', error %d\n", wine_dbgstr_w(state->database_file), ret );
+        return 0;
+    }
+    return 1;
+}
+
+static void close_database( struct msidb_state *state )
+{
+    UINT ret;
+
+    ret = MsiDatabaseCommit( state->database_handle );
+    if (ret != ERROR_SUCCESS)
+    {
+        ERR( "Failed to commit changes to database.\n" );
+        return;
+    }
+    ret = MsiCloseHandle( state->database_handle );
+    if (ret != ERROR_SUCCESS)
+    {
+        WARN( "Failed to close database handle.\n" );
+        return;
+    }
+}
+
+int wmain( int argc, WCHAR *argv[] )
+{
+    struct msidb_state state;
+    int i, n = 1;
+
+    memset( &state, 0x0, sizeof(state) );
+    /* process and validate all the command line flags */
+    for (i = 1; n && i < argc; i += n)
+        n = process_argument( &state, i, argc, argv );
+    if (!valid_state( &state ))
+        return 1;
+
+    /* perform the requested operations */
+    if (!open_database( &state ))
+    {
+        ERR( "Failed to open database '%s'.\n", wine_dbgstr_w(state.database_file) );
+        return 1;
+    }
+    close_database( &state );
+    return 0;
+}




More information about the wine-cvs mailing list