From: "Erich E. Hoover" <erich.e.hoover(a)gmail.com>
The _SummaryInformation table stores a lot of important information
about an MSI database. This patch adds the ability to export that
table since, like _ForceCodepage, it is stored in a different format
than the other tables.
v2: Avoid lstrlenA calls.
Signed-off-by: Erich E. Hoover <erich.e.hoover(a)gmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msi/database.c | 29 +++++++++---
dlls/msi/msipriv.h | 1 +
dlls/msi/suminfo.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 133 insertions(+), 6 deletions(-)
diff --git a/dlls/msi/database.c b/dlls/msi/database.c
index b8ec39322b..589dce510d 100644
--- a/dlls/msi/database.c
+++ b/dlls/msi/database.c
@@ -974,24 +974,35 @@ static UINT msi_export_forcecodepage( HANDLE handle, UINT codepage )
{
static const char fmt[] = "\r\n\r\n%u\t_ForceCodepage\r\n";
char data[sizeof(fmt) + 10];
- DWORD sz;
-
- sprintf( data, fmt, codepage );
+ DWORD sz = sprintf( data, fmt, codepage );
- sz = lstrlenA(data) + 1;
if (!WriteFile(handle, data, sz, &sz, NULL))
return ERROR_FUNCTION_FAILED;
return ERROR_SUCCESS;
}
-static UINT MSI_DatabaseExport( MSIDATABASE *db, LPCWSTR table,
- LPCWSTR folder, LPCWSTR file )
+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 = ARRAY_SIZE(header) - 1;
+
+ 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 query[] = {
's','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','%','s',0 };
static const WCHAR forcecodepage[] = {
'_','F','o','r','c','e','C','o','d','e','p','a','g','e',0 };
+ static const WCHAR summaryinformation[] = {
+ '_','S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0 };
MSIRECORD *rec = NULL;
MSIQUERY *view = NULL;
LPWSTR filename;
@@ -1026,6 +1037,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 4b2b65a13b..39219a646f 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -961,6 +961,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 98f6330d9f..c812ae09a4 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"
@@ -1096,6 +1097,114 @@ end:
return r;
}
+static UINT save_prop( MSISUMMARYINFO *si, HANDLE handle, UINT row )
+{
+ static const char fmt_systemtime[] = "%04u/%02u/%02u %02u:%02u:%02u";
+ char data[36]; /* 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 */
+ sz = sprintf( data, fmt_begin, row );
+ if (!WriteFile( handle, data, sz, &sz, NULL ))
+ return ERROR_WRITE_FAULT;
+
+ switch( data_type )
+ {
+ case VT_I2:
+ case VT_I4:
+ sz = sprintf( data, fmt_int, int_value );
+ 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 = len;
+ 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;
+ sz = sprintf( data, fmt_systemtime, system_time.wYear, system_time.wMonth,
+ system_time.wDay, system_time.wHour, system_time.wMinute,
+ system_time.wSecond );
+ 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 = ARRAY_SIZE(data_end) - 1;
+ 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.20.1