Module: wine Branch: master Commit: 545d0e70cf200270956193f6606eb2a9cbb2933a URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=545d0e70cf200270956193f6...
Author: James Hawkins truiken@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);