https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1cdb30ec0d4d16c77c21935836b6fe05c5ebc23b

commit 1cdb30ec0d4d16c77c21935836b6fe05c5ebc23b
Author:     winesync <[email protected]>
AuthorDate: Sun Mar 13 19:08:45 2022 +0100
Commit:     Mark Jansen <[email protected]>
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 <[email protected]>
    Signed-off-by: Hans Leidekker <[email protected]>
    Signed-off-by: Alexandre Julliard <[email protected]>
    
    wine commit id 877540b522c46134aa1b843519fa5694adb187ce by Piotr Caban 
<[email protected]>
---
 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 );

Reply via email to