msi: Fix the case where the summary information stream is already open in MsiGetSummaryInformationW.

This commit is contained in:
Hans Leidekker 2015-03-16 10:55:58 +01:00 committed by Alexandre Julliard
parent 7a4d8f57c7
commit db3fdbe1e3
5 changed files with 112 additions and 58 deletions

View File

@ -557,7 +557,7 @@ static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
{
MSISUMMARYINFO *si;
MSIDATABASE *patch_db;
UINT r = ERROR_SUCCESS;
UINT r;
r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db );
if (r != ERROR_SUCCESS)
@ -566,8 +566,8 @@ static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
return r;
}
si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
if (!si)
r = msi_get_suminfo( patch_db->storage, 0, &si );
if (r != ERROR_SUCCESS)
{
msiobj_release( &patch_db->hdr );
return ERROR_FUNCTION_FAILED;

View File

@ -951,7 +951,7 @@ extern void msi_dialog_unregister_class( void ) DECLSPEC_HIDDEN;
extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR ) DECLSPEC_HIDDEN;
/* summary information */
extern MSISUMMARYINFO *MSI_GetSummaryInformationW( IStorage *stg, UINT uiUpdateCount ) DECLSPEC_HIDDEN;
extern UINT msi_get_suminfo( IStorage *stg, UINT uiUpdateCount, MSISUMMARYINFO **si ) DECLSPEC_HIDDEN;
extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
extern INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) DECLSPEC_HIDDEN;

View File

@ -1280,7 +1280,7 @@ enum platform parse_platform( const WCHAR *str )
return PLATFORM_UNKNOWN;
}
static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
{
WCHAR *template, *p, *q, *platform;
DWORD i, count;
@ -1483,10 +1483,12 @@ static WCHAR *get_package_code( MSIDATABASE *db )
{
WCHAR *ret;
MSISUMMARYINFO *si;
UINT r;
if (!(si = MSI_GetSummaryInformationW( db->storage, 0 )))
r = msi_get_suminfo( db->storage, 0, &si );
if (r != ERROR_SUCCESS)
{
WARN("failed to load summary info\n");
WARN("failed to load summary info %u\n", r);
return NULL;
}
ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
@ -1633,14 +1635,14 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
package->localfile = strdupW( localfile );
package->delete_on_close = delete_on_close;
si = MSI_GetSummaryInformationW( db->storage, 0 );
if (!si)
r = msi_get_suminfo( db->storage, 0, &si );
if (r != ERROR_SUCCESS)
{
WARN("failed to load summary info\n");
msiobj_release( &package->hdr );
return ERROR_INSTALL_PACKAGE_INVALID;
}
r = msi_parse_summary( si, package );
r = parse_suminfo( si, package );
msiobj_release( &si->hdr );
if (r != ERROR_SUCCESS)
{

View File

@ -124,15 +124,16 @@ static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *transform
MSITRANSFORM_VALIDATE_PRODUCT | MSITRANSFORM_VALIDATE_LANGUAGE |
MSITRANSFORM_VALIDATE_PLATFORM | MSITRANSFORM_VALIDATE_MAJORVERSION |
MSITRANSFORM_VALIDATE_MINORVERSION | MSITRANSFORM_VALIDATE_UPGRADECODE;
MSISUMMARYINFO *si = MSI_GetSummaryInformationW( transform, 0 );
UINT valid_flags = 0, wanted_flags = 0;
MSISUMMARYINFO *si;
UINT r, valid_flags = 0, wanted_flags = 0;
WCHAR *template, *product, *p;
struct transform_desc *desc;
if (!si)
r = msi_get_suminfo( transform, 0, &si );
if (r != ERROR_SUCCESS)
{
WARN("no summary information!\n");
return ERROR_FUNCTION_FAILED;
return r;
}
wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
wanted_flags &= 0xffff; /* mask off error condition flags */
@ -886,7 +887,7 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, const WCHAR *file )
WCHAR localfile[MAX_PATH];
MSISUMMARYINFO *si;
MSIPATCHINFO *patch = NULL;
UINT r = ERROR_SUCCESS;
UINT r;
TRACE("%p, %s\n", package, debugstr_w(file));
@ -896,10 +897,11 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, const WCHAR *file )
ERR("failed to open patch collection %s\n", debugstr_w( file ) );
return r;
}
if (!(si = MSI_GetSummaryInformationW( patch_db->storage, 0 )))
r = msi_get_suminfo( patch_db->storage, 0, &si );
if (r != ERROR_SUCCESS)
{
msiobj_release( &patch_db->hdr );
return ERROR_FUNCTION_FAILED;
return r;
}
r = msi_check_patch_applicable( package, si );
if (r != ERROR_SUCCESS)
@ -1019,11 +1021,11 @@ UINT msi_apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code )
ERR("failed to open patch database %s\n", debugstr_w( patch_file ));
return r;
}
si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
if (!si)
r = msi_get_suminfo( patch_db->storage, 0, &si );
if (r != ERROR_SUCCESS)
{
msiobj_release( &patch_db->hdr );
return ERROR_FUNCTION_FAILED;
return r;
}
r = msi_parse_patch_summary( si, &patch_info );
msiobj_release( &si->hdr );

View File

@ -235,7 +235,6 @@ static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz
static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
{
UINT ret = ERROR_FUNCTION_FAILED;
PROPERTYSETHEADER set_hdr;
FORMATIDOFFSET format_hdr;
PROPERTYSECTIONHEADER section_hdr;
@ -250,44 +249,44 @@ static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
sz = sizeof set_hdr;
r = IStream_Read( stm, &set_hdr, sz, &count );
if( FAILED(r) || count != sz )
return ret;
return ERROR_FUNCTION_FAILED;
if( set_hdr.wByteOrder != 0xfffe )
{
ERR("property set not big-endian %04X\n", set_hdr.wByteOrder);
return ret;
return ERROR_FUNCTION_FAILED;
}
sz = sizeof format_hdr;
r = IStream_Read( stm, &format_hdr, sz, &count );
if( FAILED(r) || count != sz )
return ret;
return ERROR_FUNCTION_FAILED;
/* check the format id is correct */
if( !IsEqualGUID( &FMTID_SummaryInformation, &format_hdr.fmtid ) )
return ret;
return ERROR_FUNCTION_FAILED;
/* seek to the location of the section */
ofs.QuadPart = format_hdr.dwOffset;
r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, NULL );
if( FAILED(r) )
return ret;
return ERROR_FUNCTION_FAILED;
/* read the section itself */
sz = SECT_HDR_SIZE;
r = IStream_Read( stm, &section_hdr, sz, &count );
if( FAILED(r) || count != sz )
return ret;
return ERROR_FUNCTION_FAILED;
if( section_hdr.cProperties > MSI_MAX_PROPS )
{
ERR("too many properties %d\n", section_hdr.cProperties);
return ret;
return ERROR_FUNCTION_FAILED;
}
data = msi_alloc( section_hdr.cbSection);
if( !data )
return ret;
return ERROR_FUNCTION_FAILED;
memcpy( data, &section_hdr, SECT_HDR_SIZE );
@ -300,7 +299,7 @@ static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
ERR("failed to read properties %d %d\n", count, sz);
msi_free( data );
return ret;
return ERROR_SUCCESS;
}
static DWORD write_dword( LPBYTE data, DWORD ofs, DWORD val )
@ -426,34 +425,75 @@ static UINT save_summary_info( const MSISUMMARYINFO * si, IStream *stm )
return ERROR_SUCCESS;
}
MSISUMMARYINFO *MSI_GetSummaryInformationW( IStorage *stg, UINT uiUpdateCount )
static MSISUMMARYINFO *create_suminfo( IStorage *stg, UINT update_count )
{
IStream *stm = NULL;
MSISUMMARYINFO *si;
DWORD grfMode;
HRESULT r;
TRACE("%p %d\n", stg, uiUpdateCount );
if (!(si = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO, sizeof(MSISUMMARYINFO), MSI_CloseSummaryInfo )))
return NULL;
si = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO,
sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
if( !si )
return si;
si->update_count = uiUpdateCount;
si->update_count = update_count;
IStorage_AddRef( stg );
si->storage = stg;
/* read the stream... if we fail, we'll start with an empty property set */
grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE;
r = IStorage_OpenStream( si->storage, szSumInfo, 0, grfMode, 0, &stm );
if( SUCCEEDED(r) )
return si;
}
UINT msi_get_suminfo( IStorage *stg, UINT uiUpdateCount, MSISUMMARYINFO **ret )
{
IStream *stm;
MSISUMMARYINFO *si;
HRESULT hr;
UINT r;
TRACE("%p, %u\n", stg, uiUpdateCount);
if (!(si = create_suminfo( stg, uiUpdateCount ))) return ERROR_OUTOFMEMORY;
hr = IStorage_OpenStream( si->storage, szSumInfo, 0, STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stm );
if (FAILED( hr ))
{
load_summary_info( si, stm );
IStream_Release( stm );
msiobj_release( &si->hdr );
return ERROR_FUNCTION_FAILED;
}
return si;
r = load_summary_info( si, stm );
IStream_Release( stm );
if (r != ERROR_SUCCESS)
{
msiobj_release( &si->hdr );
return r;
}
*ret = si;
return ERROR_SUCCESS;
}
static UINT get_db_suminfo( MSIDATABASE *db, UINT uiUpdateCount, MSISUMMARYINFO **ret )
{
IStream *stm;
MSISUMMARYINFO *si;
UINT r;
if (!(si = create_suminfo( db->storage, uiUpdateCount ))) return ERROR_OUTOFMEMORY;
r = msi_get_stream( db, szSumInfo, &stm );
if (r != ERROR_SUCCESS)
{
msiobj_release( &si->hdr );
return r;
}
r = load_summary_info( si, stm );
IStream_Release( stm );
if (r != ERROR_SUCCESS)
{
msiobj_release( &si->hdr );
return r;
}
*ret = si;
return ERROR_SUCCESS;
}
UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
@ -461,7 +501,7 @@ UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
{
MSISUMMARYINFO *si;
MSIDATABASE *db;
UINT ret = ERROR_FUNCTION_FAILED;
UINT ret;
TRACE("%d %s %d %p\n", hDatabase, debugstr_w(szDatabase),
uiUpdateCount, pHandle);
@ -505,8 +545,16 @@ UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
}
}
si = MSI_GetSummaryInformationW( db->storage, uiUpdateCount );
if (si)
ret = msi_get_suminfo( db->storage, uiUpdateCount, &si );
if (ret != ERROR_SUCCESS)
ret = get_db_suminfo( db, uiUpdateCount, &si );
if (ret != ERROR_SUCCESS)
{
if ((si = create_suminfo( db->storage, uiUpdateCount )))
ret = ERROR_SUCCESS;
}
if (ret == ERROR_SUCCESS)
{
*pHandle = alloc_msihandle( &si->hdr );
if( *pHandle )
@ -658,9 +706,10 @@ LPWSTR msi_get_suminfo_product( IStorage *stg )
{
MSISUMMARYINFO *si;
LPWSTR prod;
UINT r;
si = MSI_GetSummaryInformationW( stg, 0 );
if (!si)
r = msi_get_suminfo( stg, 0, &si );
if (r != ERROR_SUCCESS)
{
ERR("no summary information!\n");
return NULL;
@ -921,15 +970,16 @@ static UINT parse_prop( LPCWSTR prop, LPCWSTR value, UINT *pid, INT *int_value,
UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns )
{
UINT r = ERROR_FUNCTION_FAILED;
UINT r;
int i, j;
MSISUMMARYINFO *si;
si = MSI_GetSummaryInformationW( db->storage, num_records * (num_columns / 2) );
if (!si)
r = msi_get_suminfo( db->storage, num_records * (num_columns / 2), &si );
if (r != ERROR_SUCCESS)
{
ERR("no summary information!\n");
return ERROR_FUNCTION_FAILED;
if (!(si = create_suminfo( db->storage, num_records * (num_columns / 2) )))
return ERROR_OUTOFMEMORY;
r = ERROR_SUCCESS;
}
for (i = 0; i < num_records; i++)