James Hawkins : msi: Disable child features of parent features that are unselected because of the install level .

Alexandre Julliard julliard at wine.codeweavers.com
Mon Sep 25 09:46:45 CDT 2006


Module: wine
Branch: master
Commit: 545d0e70cf200270956193f6606eb2a9cbb2933a
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=545d0e70cf200270956193f6606eb2a9cbb2933a

Author: James Hawkins <truiken at gmail.com>
Date:   Wed Sep 20 19:59:19 2006 -0700

msi: Disable child features of parent features that are unselected because of the install level.

---

 dlls/msi/action.c        |   71 +++++++++++++++++++++++++++++++++++++++++++++-
 dlls/msi/action.h        |    7 +++++
 dlls/msi/helpers.c       |    7 +++++
 dlls/msi/tests/package.c |   22 ++++++++++++++
 4 files changed, 105 insertions(+), 2 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index a1729d3..037d509 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -1163,6 +1163,19 @@ static UINT add_feature_component( MSIFE
     return ERROR_SUCCESS;
 }
 
+static UINT add_feature_child( MSIFEATURE *parent, MSIFEATURE *child )
+{
+    FeatureList *fl;
+
+    fl = msi_alloc( sizeof(*fl) );
+    if ( !fl )
+        return ERROR_NOT_ENOUGH_MEMORY;
+    fl->feature = child;
+    list_add_tail( &parent->Children, &fl->entry );
+
+    return ERROR_SUCCESS;
+}
+
 static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
 {
     _ilfs* ilfs= (_ilfs*)param;
@@ -1185,6 +1198,19 @@ static UINT iterate_load_featurecomponen
     return ERROR_SUCCESS;
 }
 
+static MSIFEATURE *find_feature_by_name( MSIPACKAGE *package, LPCWSTR name )
+{
+    MSIFEATURE *feature;
+
+    LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
+    {
+        if ( !lstrcmpW( feature->Feature, name ) )
+            return feature;
+    }
+
+    return NULL;
+}
+
 static UINT load_feature(MSIRECORD * row, LPVOID param)
 {
     MSIPACKAGE* package = (MSIPACKAGE*)param;
@@ -1206,6 +1232,7 @@ static UINT load_feature(MSIRECORD * row
     if (!feature)
         return ERROR_NOT_ENOUGH_MEMORY;
 
+    list_init( &feature->Children );
     list_init( &feature->Components );
     
     feature->Feature = msi_dup_record_field( row, 1 );
@@ -1244,6 +1271,26 @@ static UINT load_feature(MSIRECORD * row
     return ERROR_SUCCESS;
 }
 
+static UINT find_feature_children(MSIRECORD * row, LPVOID param)
+{
+    MSIPACKAGE* package = (MSIPACKAGE*)param;
+    MSIFEATURE *parent, *child;
+
+    child = find_feature_by_name( package, MSI_RecordGetString( row, 1 ) );
+    if (!child)
+        return ERROR_FUNCTION_FAILED;
+
+    if (!child->Feature_Parent)
+        return ERROR_SUCCESS;
+
+    parent = find_feature_by_name( package, child->Feature_Parent );
+    if (!parent)
+        return ERROR_FUNCTION_FAILED;
+
+    add_feature_child( parent, child );
+    return ERROR_SUCCESS;
+}
+
 static UINT load_all_features( MSIPACKAGE *package )
 {
     static const WCHAR query[] = {
@@ -1261,7 +1308,12 @@ static UINT load_all_features( MSIPACKAG
         return r;
 
     r = MSI_IterateRecords( view, NULL, load_feature, package );
+    if (r != ERROR_SUCCESS)
+        return r;
+
+    r = MSI_IterateRecords( view, NULL, find_feature_children, package );
     msiobj_release( &view->hdr );
+
     return r;
 }
 
@@ -1542,7 +1594,7 @@ static void ACTION_UpdateInstallStates(M
     LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
     {
         ComponentList *cl;
-        INSTALLSTATE res = -10;
+        INSTALLSTATE res = INSTALLSTATE_ABSENT;
 
         LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
         {
@@ -1554,7 +1606,7 @@ static void ACTION_UpdateInstallStates(M
                 break;
             }
 
-            if (res == -10)
+            if (res == INSTALLSTATE_ABSENT)
                 res = comp->Installed;
             else
             {
@@ -1693,6 +1745,21 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *pa
                 }
             }
         }
+
+        /* disable child features of unselected parent features */
+        LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
+        {
+            FeatureList *fl;
+
+            if (feature->Level > 0 && feature->Level <= install_level)
+                continue;
+
+            LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry )
+            {
+                fl->feature->ActionRequest = INSTALLSTATE_UNKNOWN;
+                fl->feature->Action = INSTALLSTATE_UNKNOWN;
+            }
+        }
     }
     else
     {
diff --git a/dlls/msi/action.h b/dlls/msi/action.h
index 785c4e3..ae7de82 100644
--- a/dlls/msi/action.h
+++ b/dlls/msi/action.h
@@ -39,6 +39,7 @@ typedef struct tagMSIFEATURE
     INSTALLSTATE ActionRequest;
     INSTALLSTATE Action;
 
+    struct list Children;
     struct list Components;
     
     INT Cost;
@@ -74,6 +75,12 @@ typedef struct tagComponentList
     MSICOMPONENT *component;
 } ComponentList;
 
+typedef struct tagFeatureList
+{
+    struct list entry;
+    MSIFEATURE *feature;
+} FeatureList;
+
 typedef struct tagMSIFOLDER
 {
     struct list entry;
diff --git a/dlls/msi/helpers.c b/dlls/msi/helpers.c
index 8c957a2..50fc992 100644
--- a/dlls/msi/helpers.c
+++ b/dlls/msi/helpers.c
@@ -404,6 +404,13 @@ static void free_feature( MSIFEATURE *fe
 {
     struct list *item, *cursor;
 
+    LIST_FOR_EACH_SAFE( item, cursor, &feature->Children )
+    {
+        FeatureList *fl = LIST_ENTRY( item, FeatureList, entry );
+        list_remove( &fl->entry );
+        msi_free( fl );
+    }
+
     LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
     {
         ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c
index 4e9d40a..cd55f89 100644
--- a/dlls/msi/tests/package.c
+++ b/dlls/msi/tests/package.c
@@ -2366,6 +2366,14 @@ static void test_featureparents(void)
     r = add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
 
+    /* disabled because of install level */
+    r = add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
+    ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
+
+    /* child feature of disabled feature */
+    r = add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
+    ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
+
     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
     r = add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
@@ -2508,6 +2516,20 @@ static void test_featureparents(void)
 
     state = 0xdeadbee;
     action = 0xdeadbee;
+    r = MsiGetFeatureState(hpkg, "waters", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
+    ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetFeatureState(hpkg, "bayer", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
+    ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "leo", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);




More information about the wine-cvs mailing list