msi: Apply registered patches in MsiOpenPackage.
diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 35030e2..6ed1417 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -492,7 +492,7 @@
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 @@
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 @@
}
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 @@
return (level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED;
}
-static UINT msi_set_context(MSIPACKAGE *package)
+UINT msi_set_context(MSIPACKAGE *package)
{
int num;
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 354aca5..a8737a2 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -685,7 +685,10 @@
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_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 */
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 2ffd66e..e53de53 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1048,6 +1048,8 @@
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 @@
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 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 @@
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;
}
diff --git a/dlls/msi/tests/patch.c b/dlls/msi/tests/patch.c
index e386925..2c7459d 100644
--- a/dlls/msi/tests/patch.c
+++ b/dlls/msi/tests/patch.c
@@ -731,7 +731,7 @@
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 @@
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 );