msi: Apply registered patches in MsiOpenPackage.

This commit is contained in:
Hans Leidekker 2010-05-05 14:37:55 +02:00 committed by Alexandre Julliard
parent 881ef98479
commit 82d7b04c2c
4 changed files with 120 additions and 27 deletions

View File

@ -492,7 +492,7 @@ done:
return r;
}
static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch )
UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch )
{
MSIPATCHINFO *pi;
UINT r = ERROR_SUCCESS;
@ -520,15 +520,40 @@ static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch )
return r;
}
UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch )
{
UINT i, r = ERROR_SUCCESS;
WCHAR **substorage;
/* apply substorage transforms */
substorage = msi_split_string( patch->transforms, ';' );
for (i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++)
r = msi_apply_substorage_transform( package, patch_db, substorage[i] );
msi_free( substorage );
if (r != ERROR_SUCCESS)
return r;
msi_set_media_source_prop( package );
/*
* There might be a CAB file in the patch package,
* so append it to the list of storages to search for streams.
*/
append_storage_to_db( package->db, patch_db->storage );
list_add_tail( &package->patches, &patch->entry );
return ERROR_SUCCESS;
}
static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
{
static const WCHAR dotmsp[] = {'.','m','s','p',0};
MSIDATABASE *patch_db = NULL;
WCHAR localfile[MAX_PATH];
LPWSTR *substorage;
MSISUMMARYINFO *si;
MSIPATCHINFO *patch = NULL;
UINT i, r = ERROR_SUCCESS;
UINT r = ERROR_SUCCESS;
TRACE("%p %s\n", package, debugstr_w( file ) );
@ -573,23 +598,9 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
}
patch->localfile = strdupW( localfile );
/* apply substorage transforms */
substorage = msi_split_string( patch->transforms, ';' );
for ( i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++ )
r = msi_apply_substorage_transform( package, patch_db, substorage[i] );
msi_free( substorage );
if (r != ERROR_SUCCESS)
goto done;
msi_set_media_source_prop( package );
/*
* There might be a CAB file in the patch package,
* so append it to the list of storages to search for streams.
*/
append_storage_to_db( package->db, patch_db->storage );
list_add_tail( &package->patches, &patch->entry );
r = msi_apply_patch_db( package, patch_db, patch );
if ( r != ERROR_SUCCESS )
WARN("patch failed to apply %u\n", r);
done:
msiobj_release( &si->hdr );
@ -729,7 +740,7 @@ static BOOL needs_ui_sequence(MSIPACKAGE *package)
return (level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED;
}
static UINT msi_set_context(MSIPACKAGE *package)
UINT msi_set_context(MSIPACKAGE *package)
{
int num;

View File

@ -685,7 +685,10 @@ extern UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db,
LPCWSTR szTransformFile, int iErrorCond );
extern void append_storage_to_db( MSIDATABASE *db, IStorage *stg );
/* patch functions */
extern UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si );
extern UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch );
extern UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch );
/* action internals */
extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR );
@ -758,6 +761,7 @@ extern UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename );
extern UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR);
extern UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR);
extern UINT msi_clone_properties(MSIPACKAGE *);
extern UINT msi_set_context(MSIPACKAGE *);
extern UINT MSI_GetFeatureCost(MSIPACKAGE *, MSIFEATURE *, MSICOSTTREE, INSTALLSTATE, LPINT);
/* for deformating */

View File

@ -1048,6 +1048,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
msi_clone_properties( package );
package->ProductCode = msi_dup_property( package->db, szProductCode );
package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
set_installed_prop( package );
set_installer_properties( package );
@ -1167,6 +1169,60 @@ UINT msi_get_local_package_name( LPWSTR path, LPCWSTR suffix )
return ERROR_SUCCESS;
}
static UINT apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code )
{
UINT r;
DWORD len;
WCHAR patch_file[MAX_PATH];
MSIDATABASE *patch_db;
MSIPATCHINFO *patch_info;
MSISUMMARYINFO *si;
len = sizeof(patch_file) / sizeof(WCHAR);
r = MsiGetPatchInfoExW( patch_code, package->ProductCode, NULL, package->Context,
INSTALLPROPERTY_LOCALPACKAGEW, patch_file, &len );
if (r != ERROR_SUCCESS)
{
ERR("failed to get patch filename %u\n", r);
return r;
}
r = MSI_OpenDatabaseW( patch_file, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &patch_db );
if (r != ERROR_SUCCESS)
{
ERR("failed to open patch database %s\n", debugstr_w( patch_file ));
return r;
}
si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
if (!si)
{
msiobj_release( &patch_db->hdr );
return ERROR_FUNCTION_FAILED;
}
r = msi_parse_patch_summary( si, &patch_info );
msiobj_release( &si->hdr );
if (r != ERROR_SUCCESS)
{
ERR("failed to parse patch summary %u\n", r);
msiobj_release( &patch_db->hdr );
return r;
}
r = msi_apply_patch_db( package, patch_db, patch_info );
msiobj_release( &patch_db->hdr );
if (r != ERROR_SUCCESS)
{
ERR("failed to apply patch %u\n", r);
msi_free( patch_info->patchcode );
msi_free( patch_info->transforms );
msi_free( patch_info->localfile );
msi_free( patch_info );
}
return r;
}
UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
{
static const WCHAR OriginalDatabase[] =
@ -1180,6 +1236,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
UINT r;
WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH];
LPCWSTR file = szPackage;
DWORD index = 0;
TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
@ -1293,9 +1350,30 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
msi_set_property( package->db, OriginalDatabase, fullpath );
}
package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
*pPackage = package;
msi_set_context( package );
while (1)
{
WCHAR patch_code[GUID_SIZE];
r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context,
MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL );
if (r != ERROR_SUCCESS)
break;
TRACE("found registered patch %s\n", debugstr_w(patch_code));
r = apply_registered_patch( package, patch_code );
if (r != ERROR_SUCCESS)
{
ERR("registered patch failed to apply %u\n", r);
MSI_FreePackage( (MSIOBJECTHDR *)package );
return r;
}
index++;
}
*pPackage = package;
return ERROR_SUCCESS;
}

View File

@ -731,7 +731,7 @@ static void test_simple_patch( void )
ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
r = MsiViewFetch( hview, &hrec );
todo_wine ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r );
MsiCloseHandle( hrec );
MsiViewClose( hview );
@ -942,13 +942,13 @@ static void test_system_tables( void )
ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
r = find_entry( hdb, "_Tables", "MsiPatchHeaders" );
todo_wine ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
r = find_entry( hdb, "_Tables", "Patch" );
todo_wine ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
r = find_entry( hdb, "_Tables", "PatchPackage" );
todo_wine ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r );
MsiCloseHandle( hdb );
MsiCloseHandle( hproduct );