summaryrefslogtreecommitdiffstats
path: root/libmsi
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2012-12-19 11:54:19 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2013-01-09 13:56:07 +0100
commit82f273547b1d7c2cb01fd238ba6d0ac001ed15e9 (patch)
tree264035073ba0216344205f84dfd6aeec4457903c /libmsi
parent1732293217d3bd81dde1cbafc3201cdacfeb1a2b (diff)
downloadmsitools-82f273547b1d7c2cb01fd238ba6d0ac001ed15e9.tar.gz
msitools-82f273547b1d7c2cb01fd238ba6d0ac001ed15e9.tar.xz
msitools-82f273547b1d7c2cb01fd238ba6d0ac001ed15e9.zip
database: export special _SummaryInformation table
See http://msdn.microsoft.com/es-es/library/windows/desktop/aa372921%28v=vs.85%29.aspx
Diffstat (limited to 'libmsi')
-rw-r--r--libmsi/libmsi-database.c57
-rw-r--r--libmsi/libmsi-summary-info.c39
-rw-r--r--libmsi/msipriv.h1
3 files changed, 87 insertions, 10 deletions
diff --git a/libmsi/libmsi-database.c b/libmsi/libmsi-database.c
index 5ef0dac..5bf3321 100644
--- a/libmsi/libmsi-database.c
+++ b/libmsi/libmsi-database.c
@@ -1287,7 +1287,7 @@ static unsigned msi_export_row( LibmsiRecord *row, void *arg )
export->table_dir, export->error);
}
-static unsigned msi_export_forcecodepage( int fd, unsigned codepage )
+static LibmsiResult msi_export_forcecodepage( int fd, unsigned codepage )
{
static const char fmt[] = "\r\n\r\n%u\t_ForceCodepage\r\n";
char data[sizeof(fmt) + 10];
@@ -1302,22 +1302,60 @@ static unsigned msi_export_forcecodepage( int fd, unsigned codepage )
return LIBMSI_RESULT_SUCCESS;
}
-static unsigned _libmsi_database_export(LibmsiDatabase *db, const char *table,
+static LibmsiResult msi_export_summaryinfo (LibmsiDatabase *db, int fd, GError **error)
+{
+ static const char header[] =
+ "PropertyId\tValue\r\ni2\tl255\r\n_SummaryInformation\tPropertyId\r\n";
+ LibmsiResult result = LIBMSI_RESULT_FUNCTION_FAILED;
+ LibmsiSummaryInfo *si = libmsi_summary_info_new (db, 0, error);
+ gchar *str = NULL;
+ gssize sz;
+ int i;
+
+ if (!si)
+ goto end;
+
+ sz = strlen (header);
+ if (write (fd, header, sz) != sz)
+ goto end;
+
+ for (i = 0; i < MSI_MAX_PROPS; i++)
+ if (si->property[i].vt != OLEVT_EMPTY) {
+ gchar *val = summary_info_as_string (si, i);
+ if (!val)
+ goto end;
+ gchar *str = g_strdup_printf ("%d\t%s\r\n", i, val);
+ sz = strlen (str);
+ if (write (fd, str, sz) != sz)
+ goto end;
+ g_free (str);
+ str = NULL;
+ }
+
+ result = LIBMSI_RESULT_SUCCESS;
+
+end:
+ g_free (str);
+ if (si)
+ g_object_unref (si);
+ return result;
+}
+
+static LibmsiResult _libmsi_database_export(LibmsiDatabase *db, const char *table,
int fd, GError **error)
{
static const char query[] = "select * from %s";
- static const char forcecodepage[] = "_ForceCodepage";
LibmsiRecord *rec = NULL;
LibmsiQuery *view = NULL;
- unsigned r;
+ LibmsiResult r;
TRACE("%p %s %d\n", db, debugstr_a(table), fd );
- if (!strcmp( table, forcecodepage ))
- {
- unsigned codepage = msi_get_string_table_codepage( db->strings );
- r = msi_export_forcecodepage( fd, codepage );
- goto done;
+ if (!strcmp(table, "_ForceCodepage")) {
+ unsigned codepage = msi_get_string_table_codepage (db->strings);
+ return msi_export_forcecodepage (fd, codepage);
+ } else if (!strcmp (table, "_SummaryInformation")) {
+ return msi_export_summaryinfo (db, fd, error);
}
r = _libmsi_query_open( db, &view, query, table );
@@ -1360,7 +1398,6 @@ static unsigned _libmsi_database_export(LibmsiDatabase *db, const char *table,
g_object_unref (view);
}
-done:
return r;
}
diff --git a/libmsi/libmsi-summary-info.c b/libmsi/libmsi-summary-info.c
index d8b5ed7..6ff6200 100644
--- a/libmsi/libmsi-summary-info.c
+++ b/libmsi/libmsi-summary-info.c
@@ -236,6 +236,23 @@ static unsigned read_dword( const uint8_t *data, unsigned *ofs )
return val;
}
+static gchar* filetime_to_string (guint64 ft)
+{
+ struct tm tm;
+ time_t t;
+
+ ft /= 10000000ULL;
+ ft -= 134774ULL * 86400ULL;
+ t = ft;
+
+ if (!gmtime_r (&t, &tm))
+ return NULL;
+
+ return g_strdup_printf ("%d/%d/%d %d:%d:%d",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
static void parse_filetime( const char *str, guint64 *ft )
{
/* set to 0, tm_isdst can make the result vary: */
@@ -602,6 +619,28 @@ libmsi_summary_info_get_property_type (LibmsiSummaryInfo *self,
}
}
+G_GNUC_INTERNAL gchar *
+summary_info_as_string (LibmsiSummaryInfo *si, unsigned uiProperty)
+{
+ LibmsiOLEVariant *prop = &si->property[uiProperty];
+
+ switch (prop->vt) {
+ case OLEVT_I2:
+ case OLEVT_I4:
+ return g_strdup_printf ("%d", prop->intval);
+ case OLEVT_LPSTR:
+ return g_strdup (prop->strval);
+ case OLEVT_FILETIME:
+ return filetime_to_string (prop->filetime);
+ case OLEVT_EMPTY:
+ return g_strdup ("");
+ default:
+ g_warn_if_reached ();
+ }
+
+ return NULL;
+}
+
static void _summary_info_get_property (LibmsiSummaryInfo *si, unsigned uiProperty,
unsigned *puiDataType, int *pintvalue,
guint64 *pftValue, char *szValueBuf,
diff --git a/libmsi/msipriv.h b/libmsi/msipriv.h
index 4c52718..bdb2e44 100644
--- a/libmsi/msipriv.h
+++ b/libmsi/msipriv.h
@@ -416,6 +416,7 @@ extern unsigned msi_view_get_row(LibmsiDatabase *, LibmsiView *, unsigned, Libms
/* summary information */
extern unsigned msi_add_suminfo( LibmsiDatabase *db, char ***records, int num_records, int num_columns );
+gchar* summary_info_as_string (LibmsiSummaryInfo *si, unsigned uiProperty);
/* IStream internals */
LibmsiIStream * libmsi_istream_new (GsfInput *input);