msi: Add support for exporting the _SummaryInformation table.
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. Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com> Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
51d5242a5f
commit
79fd42fc1a
|
@ -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;
|
||||
DWORD sz = sprintf( data, fmt, codepage );
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue