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

This commit is contained in:
James Hawkins 2006-09-20 19:59:19 -07:00 committed by Alexandre Julliard
parent 703d77dc58
commit 545d0e70cf
4 changed files with 105 additions and 2 deletions

View File

@ -1163,6 +1163,19 @@ static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp )
return ERROR_SUCCESS; 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) static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
{ {
_ilfs* ilfs= (_ilfs*)param; _ilfs* ilfs= (_ilfs*)param;
@ -1185,6 +1198,19 @@ static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
return ERROR_SUCCESS; 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) static UINT load_feature(MSIRECORD * row, LPVOID param)
{ {
MSIPACKAGE* package = (MSIPACKAGE*)param; MSIPACKAGE* package = (MSIPACKAGE*)param;
@ -1206,6 +1232,7 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
if (!feature) if (!feature)
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
list_init( &feature->Children );
list_init( &feature->Components ); list_init( &feature->Components );
feature->Feature = msi_dup_record_field( row, 1 ); feature->Feature = msi_dup_record_field( row, 1 );
@ -1244,6 +1271,26 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
return ERROR_SUCCESS; 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 UINT load_all_features( MSIPACKAGE *package )
{ {
static const WCHAR query[] = { static const WCHAR query[] = {
@ -1261,7 +1308,12 @@ static UINT load_all_features( MSIPACKAGE *package )
return r; return r;
r = MSI_IterateRecords( view, NULL, load_feature, package ); 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 ); msiobj_release( &view->hdr );
return r; return r;
} }
@ -1542,7 +1594,7 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
ComponentList *cl; ComponentList *cl;
INSTALLSTATE res = -10; INSTALLSTATE res = INSTALLSTATE_ABSENT;
LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry ) LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{ {
@ -1554,7 +1606,7 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
break; break;
} }
if (res == -10) if (res == INSTALLSTATE_ABSENT)
res = comp->Installed; res = comp->Installed;
else else
{ {
@ -1693,6 +1745,21 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
} }
} }
} }
/* 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 else
{ {

View File

@ -39,6 +39,7 @@ typedef struct tagMSIFEATURE
INSTALLSTATE ActionRequest; INSTALLSTATE ActionRequest;
INSTALLSTATE Action; INSTALLSTATE Action;
struct list Children;
struct list Components; struct list Components;
INT Cost; INT Cost;
@ -74,6 +75,12 @@ typedef struct tagComponentList
MSICOMPONENT *component; MSICOMPONENT *component;
} ComponentList; } ComponentList;
typedef struct tagFeatureList
{
struct list entry;
MSIFEATURE *feature;
} FeatureList;
typedef struct tagMSIFOLDER typedef struct tagMSIFOLDER
{ {
struct list entry; struct list entry;

View File

@ -404,6 +404,13 @@ static void free_feature( MSIFEATURE *feature )
{ {
struct list *item, *cursor; 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 ) LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
{ {
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );

View File

@ -2366,6 +2366,14 @@ static void test_featureparents(void)
r = add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" ); r = add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r ); 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 */ /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
r = add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" ); r = add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r ); ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
@ -2506,6 +2514,20 @@ static void test_featureparents(void)
ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state); ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action); ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
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; state = 0xdeadbee;
action = 0xdeadbee; action = 0xdeadbee;
r = MsiGetComponentState(hpkg, "leo", &state, &action); r = MsiGetComponentState(hpkg, "leo", &state, &action);