diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2012-12-19 11:54:19 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-01-09 13:56:07 +0100 |
commit | 82f273547b1d7c2cb01fd238ba6d0ac001ed15e9 (patch) | |
tree | 264035073ba0216344205f84dfd6aeec4457903c /libmsi | |
parent | 1732293217d3bd81dde1cbafc3201cdacfeb1a2b (diff) | |
download | msitools-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.c | 57 | ||||
-rw-r--r-- | libmsi/libmsi-summary-info.c | 39 | ||||
-rw-r--r-- | libmsi/msipriv.h | 1 |
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); |