https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1cdb30ec0d4d16c77c219…
commit 1cdb30ec0d4d16c77c21935836b6fe05c5ebc23b
Author: winesync <ros-dev(a)reactos.org>
AuthorDate: Sun Mar 13 19:08:45 2022 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sun Mar 20 19:28:33 2022 +0100
[WINESYNC] msi: Install feature when new component is added.
Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=49350
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
wine commit id 877540b522c46134aa1b843519fa5694adb187ce by Piotr Caban
<piotr(a)codeweavers.com>
---
dll/win32/msi/action.c | 112 ++++++++++++++++++++++++++++++---
dll/win32/msi/msipriv.h | 2 +
dll/win32/msi/patch.c | 5 ++
modules/rostests/winetests/msi/patch.c | 2 +-
4 files changed, 110 insertions(+), 11 deletions(-)
diff --git a/dll/win32/msi/action.c b/dll/win32/msi/action.c
index 762d734fcbd..ee3686840a6 100644
--- a/dll/win32/msi/action.c
+++ b/dll/win32/msi/action.c
@@ -1381,6 +1381,49 @@ static UINT load_all_patches(MSIPACKAGE *package)
return rc;
}
+static UINT iterate_patched_component( MSIRECORD *row, LPVOID param )
+{
+ MSIPACKAGE *package = param;
+ const WCHAR *name;
+ MSICOMPONENT *c;
+
+ name = MSI_RecordGetString( row, 1 );
+ TRACE( "found patched component: %s\n", wine_dbgstr_w(name) );
+ c = msi_get_loaded_component( package, name );
+ if (!c)
+ return ERROR_SUCCESS;
+
+ c->updated = 1;
+ if (!wcscmp( MSI_RecordGetString( row, 2 ), L"INSERT" ))
+ c->added = 1;
+ return ERROR_SUCCESS;
+}
+
+static void mark_patched_components( MSIPACKAGE *package )
+{
+ static const WCHAR select[] = L"SELECT `Row`, `Column` FROM `_TransformView`
WHERE `Table`='Component'";
+ MSIQUERY *q;
+ UINT r;
+
+ r = MSI_OpenQuery( package->db, &q, select );
+ if (r != ERROR_SUCCESS)
+ return;
+
+ MSI_IterateRecords( q, NULL, iterate_patched_component, package );
+ msiobj_release( &q->hdr );
+
+ while (1)
+ {
+ r = MSI_OpenQuery( package->db, &q, L"ALTER TABLE `_TransformView`
FREE" );
+ if (r != ERROR_SUCCESS)
+ return;
+ r = MSI_ViewExecute( q, NULL );
+ msiobj_release( &q->hdr );
+ if (r != ERROR_SUCCESS)
+ return;
+ }
+}
+
static UINT load_folder_persistence( MSIPACKAGE *package, MSIFOLDER *folder )
{
static const WCHAR query[] = {
@@ -1525,6 +1568,7 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
msi_load_all_features( package );
load_all_files( package );
load_all_patches( package );
+ mark_patched_components( package );
load_all_media( package );
return ERROR_SUCCESS;
@@ -1809,12 +1853,6 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
}
}
}
- LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
- {
- if (feature->Feature_Parent) continue;
- disable_children( feature, level );
- follow_parent( feature );
- }
}
else if (!msi_get_property_int( package->db, szInstalled, 0 ))
{
@@ -1841,15 +1879,69 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
}
}
}
- /* disable child features of unselected parent or follow parent */
+ }
+ else
+ {
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
- if (feature->Feature_Parent) continue;
- disable_children( feature, level );
- follow_parent( feature );
+ ComponentList *cl;
+ MSIFEATURE *cur;
+
+ if (!is_feature_selected( feature, level )) continue;
+ if (feature->ActionRequest != INSTALLSTATE_UNKNOWN) continue;
+
+ LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
+ {
+ if (!cl->component->updated &&
!cl->component->added)
+ continue;
+
+ cur = feature;
+ while (cur)
+ {
+ if (cur->ActionRequest != INSTALLSTATE_UNKNOWN)
+ break;
+
+ if (cur->Installed != INSTALLSTATE_ABSENT)
+ {
+ cur->Action = cur->Installed;
+ cur->ActionRequest = cur->Installed;
+ }
+ else if (!cl->component->added)
+ {
+ break;
+ }
+ else if (cur->Attributes & msidbFeatureAttributesFavorSource)
+ {
+ cur->Action = INSTALLSTATE_SOURCE;
+ cur->ActionRequest = INSTALLSTATE_SOURCE;
+ }
+ else if (cur->Attributes &
msidbFeatureAttributesFavorAdvertise)
+ {
+ cur->Action = INSTALLSTATE_ADVERTISED;
+ cur->ActionRequest = INSTALLSTATE_ADVERTISED;
+ }
+ else
+ {
+ cur->Action = INSTALLSTATE_LOCAL;
+ cur->ActionRequest = INSTALLSTATE_LOCAL;
+ }
+
+ if (!cur->Feature_Parent)
+ break;
+ cur = msi_get_loaded_feature(package, cur->Feature_Parent);
+ }
+ }
}
}
+ /* disable child features of unselected parent or follow parent */
+ LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
+ {
+ if (feature->Feature_Parent) continue;
+ disable_children( feature, level );
+ follow_parent( feature );
+ }
+
/* now we want to set component state based based on feature state */
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
diff --git a/dll/win32/msi/msipriv.h b/dll/win32/msi/msipriv.h
index 20cf8e8b87c..503543e82e8 100644
--- a/dll/win32/msi/msipriv.h
+++ b/dll/win32/msi/msipriv.h
@@ -544,6 +544,8 @@ typedef struct tagMSICOMPONENT
unsigned int hasAdvertisedFeature:1;
unsigned int hasLocalFeature:1;
unsigned int hasSourceFeature:1;
+ unsigned int added:1;
+ unsigned int updated:1;
} MSICOMPONENT;
typedef struct tagComponentList
diff --git a/dll/win32/msi/patch.c b/dll/win32/msi/patch.c
index 1233ec306bf..67da5778415 100644
--- a/dll/win32/msi/patch.c
+++ b/dll/win32/msi/patch.c
@@ -274,9 +274,14 @@ static UINT apply_substorage_transform( MSIPACKAGE *package,
MSIDATABASE *patch_
{
ret = check_transform_applicable( package, stg );
if (ret == ERROR_SUCCESS)
+ {
+ msi_table_apply_transform( package->db, stg,
MSITRANSFORM_ERROR_VIEWTRANSFORM );
msi_table_apply_transform( package->db, stg, 0 );
+ }
else
+ {
TRACE("substorage transform %s wasn't applicable\n",
debugstr_w(name));
+ }
IStorage_Release( stg );
}
else
diff --git a/modules/rostests/winetests/msi/patch.c
b/modules/rostests/winetests/msi/patch.c
index a846defef45..87f64d6c835 100644
--- a/modules/rostests/winetests/msi/patch.c
+++ b/modules/rostests/winetests/msi/patch.c
@@ -844,7 +844,7 @@ static void test_simple_patch( void )
size = get_pf_file_size( "msitest\\patch.txt" );
ok( size == 1002, "expected 1002, got %u\n", size );
size = get_pf_file_size( "msitest\\file.txt" );
- todo_wine ok( size == 1000, "expected 1000, got %u\n", size );
+ ok( size == 1000, "expected 1000, got %u\n", size );
/* show that MsiOpenPackage applies registered patches */
r = MsiOpenPackageA( path, &hpackage );