msi: Fix the case where the summary information stream is already open in MsiGetSummaryInformationW.
This commit is contained in:
parent
7a4d8f57c7
commit
db3fdbe1e3
|
@ -557,7 +557,7 @@ static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
|
||||||
{
|
{
|
||||||
MSISUMMARYINFO *si;
|
MSISUMMARYINFO *si;
|
||||||
MSIDATABASE *patch_db;
|
MSIDATABASE *patch_db;
|
||||||
UINT r = ERROR_SUCCESS;
|
UINT r;
|
||||||
|
|
||||||
r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db );
|
r = MSI_OpenDatabaseW( patch, MSIDBOPEN_READONLY, &patch_db );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
|
@ -566,8 +566,8 @@ static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
|
r = msi_get_suminfo( patch_db->storage, 0, &si );
|
||||||
if (!si)
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
msiobj_release( &patch_db->hdr );
|
msiobj_release( &patch_db->hdr );
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
|
@ -951,7 +951,7 @@ extern void msi_dialog_unregister_class( void ) DECLSPEC_HIDDEN;
|
||||||
extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR ) DECLSPEC_HIDDEN;
|
extern UINT msi_spawn_error_dialog( MSIPACKAGE*, LPWSTR, LPWSTR ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* summary information */
|
/* 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 LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
|
||||||
extern INT msi_suminfo_get_int32( 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;
|
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -1280,7 +1280,7 @@ enum platform parse_platform( const WCHAR *str )
|
||||||
return PLATFORM_UNKNOWN;
|
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;
|
WCHAR *template, *p, *q, *platform;
|
||||||
DWORD i, count;
|
DWORD i, count;
|
||||||
|
@ -1483,10 +1483,12 @@ static WCHAR *get_package_code( MSIDATABASE *db )
|
||||||
{
|
{
|
||||||
WCHAR *ret;
|
WCHAR *ret;
|
||||||
MSISUMMARYINFO *si;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
|
ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
|
||||||
|
@ -1633,14 +1635,14 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
|
||||||
package->localfile = strdupW( localfile );
|
package->localfile = strdupW( localfile );
|
||||||
package->delete_on_close = delete_on_close;
|
package->delete_on_close = delete_on_close;
|
||||||
|
|
||||||
si = MSI_GetSummaryInformationW( db->storage, 0 );
|
r = msi_get_suminfo( db->storage, 0, &si );
|
||||||
if (!si)
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
WARN("failed to load summary info\n");
|
WARN("failed to load summary info\n");
|
||||||
msiobj_release( &package->hdr );
|
msiobj_release( &package->hdr );
|
||||||
return ERROR_INSTALL_PACKAGE_INVALID;
|
return ERROR_INSTALL_PACKAGE_INVALID;
|
||||||
}
|
}
|
||||||
r = msi_parse_summary( si, package );
|
r = parse_suminfo( si, package );
|
||||||
msiobj_release( &si->hdr );
|
msiobj_release( &si->hdr );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
|
@ -124,15 +124,16 @@ static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *transform
|
||||||
MSITRANSFORM_VALIDATE_PRODUCT | MSITRANSFORM_VALIDATE_LANGUAGE |
|
MSITRANSFORM_VALIDATE_PRODUCT | MSITRANSFORM_VALIDATE_LANGUAGE |
|
||||||
MSITRANSFORM_VALIDATE_PLATFORM | MSITRANSFORM_VALIDATE_MAJORVERSION |
|
MSITRANSFORM_VALIDATE_PLATFORM | MSITRANSFORM_VALIDATE_MAJORVERSION |
|
||||||
MSITRANSFORM_VALIDATE_MINORVERSION | MSITRANSFORM_VALIDATE_UPGRADECODE;
|
MSITRANSFORM_VALIDATE_MINORVERSION | MSITRANSFORM_VALIDATE_UPGRADECODE;
|
||||||
MSISUMMARYINFO *si = MSI_GetSummaryInformationW( transform, 0 );
|
MSISUMMARYINFO *si;
|
||||||
UINT valid_flags = 0, wanted_flags = 0;
|
UINT r, valid_flags = 0, wanted_flags = 0;
|
||||||
WCHAR *template, *product, *p;
|
WCHAR *template, *product, *p;
|
||||||
struct transform_desc *desc;
|
struct transform_desc *desc;
|
||||||
|
|
||||||
if (!si)
|
r = msi_get_suminfo( transform, 0, &si );
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
WARN("no summary information!\n");
|
WARN("no summary information!\n");
|
||||||
return ERROR_FUNCTION_FAILED;
|
return r;
|
||||||
}
|
}
|
||||||
wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
|
wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
|
||||||
wanted_flags &= 0xffff; /* mask off error condition flags */
|
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];
|
WCHAR localfile[MAX_PATH];
|
||||||
MSISUMMARYINFO *si;
|
MSISUMMARYINFO *si;
|
||||||
MSIPATCHINFO *patch = NULL;
|
MSIPATCHINFO *patch = NULL;
|
||||||
UINT r = ERROR_SUCCESS;
|
UINT r;
|
||||||
|
|
||||||
TRACE("%p, %s\n", package, debugstr_w(file));
|
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 ) );
|
ERR("failed to open patch collection %s\n", debugstr_w( file ) );
|
||||||
return r;
|
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 );
|
msiobj_release( &patch_db->hdr );
|
||||||
return ERROR_FUNCTION_FAILED;
|
return r;
|
||||||
}
|
}
|
||||||
r = msi_check_patch_applicable( package, si );
|
r = msi_check_patch_applicable( package, si );
|
||||||
if (r != ERROR_SUCCESS)
|
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 ));
|
ERR("failed to open patch database %s\n", debugstr_w( patch_file ));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
|
r = msi_get_suminfo( patch_db->storage, 0, &si );
|
||||||
if (!si)
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
msiobj_release( &patch_db->hdr );
|
msiobj_release( &patch_db->hdr );
|
||||||
return ERROR_FUNCTION_FAILED;
|
return r;
|
||||||
}
|
}
|
||||||
r = msi_parse_patch_summary( si, &patch_info );
|
r = msi_parse_patch_summary( si, &patch_info );
|
||||||
msiobj_release( &si->hdr );
|
msiobj_release( &si->hdr );
|
||||||
|
|
|
@ -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 )
|
static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
|
||||||
{
|
{
|
||||||
UINT ret = ERROR_FUNCTION_FAILED;
|
|
||||||
PROPERTYSETHEADER set_hdr;
|
PROPERTYSETHEADER set_hdr;
|
||||||
FORMATIDOFFSET format_hdr;
|
FORMATIDOFFSET format_hdr;
|
||||||
PROPERTYSECTIONHEADER section_hdr;
|
PROPERTYSECTIONHEADER section_hdr;
|
||||||
|
@ -250,44 +249,44 @@ static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
|
||||||
sz = sizeof set_hdr;
|
sz = sizeof set_hdr;
|
||||||
r = IStream_Read( stm, &set_hdr, sz, &count );
|
r = IStream_Read( stm, &set_hdr, sz, &count );
|
||||||
if( FAILED(r) || count != sz )
|
if( FAILED(r) || count != sz )
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
if( set_hdr.wByteOrder != 0xfffe )
|
if( set_hdr.wByteOrder != 0xfffe )
|
||||||
{
|
{
|
||||||
ERR("property set not big-endian %04X\n", set_hdr.wByteOrder);
|
ERR("property set not big-endian %04X\n", set_hdr.wByteOrder);
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sz = sizeof format_hdr;
|
sz = sizeof format_hdr;
|
||||||
r = IStream_Read( stm, &format_hdr, sz, &count );
|
r = IStream_Read( stm, &format_hdr, sz, &count );
|
||||||
if( FAILED(r) || count != sz )
|
if( FAILED(r) || count != sz )
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
/* check the format id is correct */
|
/* check the format id is correct */
|
||||||
if( !IsEqualGUID( &FMTID_SummaryInformation, &format_hdr.fmtid ) )
|
if( !IsEqualGUID( &FMTID_SummaryInformation, &format_hdr.fmtid ) )
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
/* seek to the location of the section */
|
/* seek to the location of the section */
|
||||||
ofs.QuadPart = format_hdr.dwOffset;
|
ofs.QuadPart = format_hdr.dwOffset;
|
||||||
r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, NULL );
|
r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, NULL );
|
||||||
if( FAILED(r) )
|
if( FAILED(r) )
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
/* read the section itself */
|
/* read the section itself */
|
||||||
sz = SECT_HDR_SIZE;
|
sz = SECT_HDR_SIZE;
|
||||||
r = IStream_Read( stm, §ion_hdr, sz, &count );
|
r = IStream_Read( stm, §ion_hdr, sz, &count );
|
||||||
if( FAILED(r) || count != sz )
|
if( FAILED(r) || count != sz )
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
if( section_hdr.cProperties > MSI_MAX_PROPS )
|
if( section_hdr.cProperties > MSI_MAX_PROPS )
|
||||||
{
|
{
|
||||||
ERR("too many properties %d\n", section_hdr.cProperties);
|
ERR("too many properties %d\n", section_hdr.cProperties);
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = msi_alloc( section_hdr.cbSection);
|
data = msi_alloc( section_hdr.cbSection);
|
||||||
if( !data )
|
if( !data )
|
||||||
return ret;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
memcpy( data, §ion_hdr, SECT_HDR_SIZE );
|
memcpy( data, §ion_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);
|
ERR("failed to read properties %d %d\n", count, sz);
|
||||||
|
|
||||||
msi_free( data );
|
msi_free( data );
|
||||||
return ret;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD write_dword( LPBYTE data, DWORD ofs, DWORD val )
|
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;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
MSISUMMARYINFO *MSI_GetSummaryInformationW( IStorage *stg, UINT uiUpdateCount )
|
static MSISUMMARYINFO *create_suminfo( IStorage *stg, UINT update_count )
|
||||||
{
|
{
|
||||||
IStream *stm = NULL;
|
|
||||||
MSISUMMARYINFO *si;
|
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,
|
si->update_count = update_count;
|
||||||
sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
|
|
||||||
if( !si )
|
|
||||||
return si;
|
|
||||||
|
|
||||||
si->update_count = uiUpdateCount;
|
|
||||||
IStorage_AddRef( stg );
|
IStorage_AddRef( stg );
|
||||||
si->storage = stg;
|
si->storage = stg;
|
||||||
|
|
||||||
/* read the stream... if we fail, we'll start with an empty property set */
|
return si;
|
||||||
grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE;
|
}
|
||||||
r = IStorage_OpenStream( si->storage, szSumInfo, 0, grfMode, 0, &stm );
|
|
||||||
if( SUCCEEDED(r) )
|
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 );
|
msiobj_release( &si->hdr );
|
||||||
IStream_Release( stm );
|
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,
|
UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
|
||||||
|
@ -461,7 +501,7 @@ UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
|
||||||
{
|
{
|
||||||
MSISUMMARYINFO *si;
|
MSISUMMARYINFO *si;
|
||||||
MSIDATABASE *db;
|
MSIDATABASE *db;
|
||||||
UINT ret = ERROR_FUNCTION_FAILED;
|
UINT ret;
|
||||||
|
|
||||||
TRACE("%d %s %d %p\n", hDatabase, debugstr_w(szDatabase),
|
TRACE("%d %s %d %p\n", hDatabase, debugstr_w(szDatabase),
|
||||||
uiUpdateCount, pHandle);
|
uiUpdateCount, pHandle);
|
||||||
|
@ -505,8 +545,16 @@ UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
si = MSI_GetSummaryInformationW( db->storage, uiUpdateCount );
|
ret = msi_get_suminfo( db->storage, uiUpdateCount, &si );
|
||||||
if (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 );
|
*pHandle = alloc_msihandle( &si->hdr );
|
||||||
if( *pHandle )
|
if( *pHandle )
|
||||||
|
@ -658,9 +706,10 @@ LPWSTR msi_get_suminfo_product( IStorage *stg )
|
||||||
{
|
{
|
||||||
MSISUMMARYINFO *si;
|
MSISUMMARYINFO *si;
|
||||||
LPWSTR prod;
|
LPWSTR prod;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
si = MSI_GetSummaryInformationW( stg, 0 );
|
r = msi_get_suminfo( stg, 0, &si );
|
||||||
if (!si)
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("no summary information!\n");
|
ERR("no summary information!\n");
|
||||||
return NULL;
|
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 msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns )
|
||||||
{
|
{
|
||||||
UINT r = ERROR_FUNCTION_FAILED;
|
UINT r;
|
||||||
int i, j;
|
int i, j;
|
||||||
MSISUMMARYINFO *si;
|
MSISUMMARYINFO *si;
|
||||||
|
|
||||||
si = MSI_GetSummaryInformationW( db->storage, num_records * (num_columns / 2) );
|
r = msi_get_suminfo( db->storage, num_records * (num_columns / 2), &si );
|
||||||
if (!si)
|
if (r != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("no summary information!\n");
|
if (!(si = create_suminfo( db->storage, num_records * (num_columns / 2) )))
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_OUTOFMEMORY;
|
||||||
|
r = ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_records; i++)
|
for (i = 0; i < num_records; i++)
|
||||||
|
|
Loading…
Reference in New Issue