Commit 1da2858c authored by Mike McCormack's avatar Mike McCormack Committed by Alexandre Julliard

- build a standard Wine list of features instead of using an array

- use feature pointers instead of array indexes
parent e5131213
...@@ -1007,7 +1007,7 @@ static MSICOMPONENT* load_component( MSIRECORD * row ) ...@@ -1007,7 +1007,7 @@ static MSICOMPONENT* load_component( MSIRECORD * row )
typedef struct { typedef struct {
MSIPACKAGE *package; MSIPACKAGE *package;
INT index; MSIFEATURE *feature;
} _ilfs; } _ilfs;
static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp ) static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp )
...@@ -1018,7 +1018,7 @@ static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp ) ...@@ -1018,7 +1018,7 @@ static UINT add_feature_component( MSIFEATURE *feature, MSICOMPONENT *comp )
if ( !cl ) if ( !cl )
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
cl->component = comp; cl->component = comp;
list_add_tail( feature->Components, &cl->entry ); list_add_tail( &feature->Components, &cl->entry );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
...@@ -1027,6 +1027,7 @@ static UINT iterate_component_check( MSIRECORD *row, LPVOID param ) ...@@ -1027,6 +1027,7 @@ static UINT iterate_component_check( MSIRECORD *row, LPVOID param )
{ {
_ilfs* ilfs= (_ilfs*)param; _ilfs* ilfs= (_ilfs*)param;
MSIPACKAGE *package = ilfs->package; MSIPACKAGE *package = ilfs->package;
MSIFEATURE *feature = ilfs->feature;
MSICOMPONENT *comp; MSICOMPONENT *comp;
comp = load_component( row ); comp = load_component( row );
...@@ -1034,7 +1035,7 @@ static UINT iterate_component_check( MSIRECORD *row, LPVOID param ) ...@@ -1034,7 +1035,7 @@ static UINT iterate_component_check( MSIRECORD *row, LPVOID param )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
list_add_tail( &package->components, &comp->entry ); list_add_tail( &package->components, &comp->entry );
add_feature_component( &package->features[ilfs->index], comp ); add_feature_component( feature, comp );
TRACE("Loaded new component %p\n", comp); TRACE("Loaded new component %p\n", comp);
...@@ -1062,7 +1063,7 @@ static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param) ...@@ -1062,7 +1063,7 @@ static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
if (comp) if (comp)
{ {
TRACE("Component %s already loaded\n", debugstr_w(component) ); TRACE("Component %s already loaded\n", debugstr_w(component) );
add_feature_component( &ilfs->package->features[ilfs->index], comp ); add_feature_component( ilfs->feature, comp );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
...@@ -1079,7 +1080,7 @@ static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param) ...@@ -1079,7 +1080,7 @@ static UINT iterate_load_featurecomponents(MSIRECORD *row, LPVOID param)
static UINT load_feature(MSIRECORD * row, LPVOID param) static UINT load_feature(MSIRECORD * row, LPVOID param)
{ {
MSIPACKAGE* package = (MSIPACKAGE*)param; MSIPACKAGE* package = (MSIPACKAGE*)param;
int index = package->loaded_features; MSIFEATURE* feature;
DWORD sz; DWORD sz;
static const WCHAR Query1[] = static const WCHAR Query1[] =
{'S','E','L','E','C','T',' ', {'S','E','L','E','C','T',' ',
...@@ -1092,67 +1093,57 @@ static UINT load_feature(MSIRECORD * row, LPVOID param) ...@@ -1092,67 +1093,57 @@ static UINT load_feature(MSIRECORD * row, LPVOID param)
UINT rc; UINT rc;
_ilfs ilfs; _ilfs ilfs;
ilfs.package = package;
ilfs.index = index;
/* fill in the data */ /* fill in the data */
package->loaded_features ++; feature = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (MSIFEATURE) );
if (package->loaded_features == 1) if (!feature)
package->features = HeapAlloc(GetProcessHeap(),0,sizeof(MSIFEATURE)); return ERROR_NOT_ENOUGH_MEMORY;
else
package->features = HeapReAlloc(GetProcessHeap(),0,package->features,
package->loaded_features * sizeof(MSIFEATURE));
memset(&package->features[index],0,sizeof(MSIFEATURE));
/* list_init( &feature->Components );
* Can't use struct list in features because the address keeps changing
* due to the above HeapReAlloc, so allocate a struct list instead
*/
package->features[index].Components =
HeapAlloc( GetProcessHeap(), 0, sizeof (struct list) );
list_init( package->features[index].Components );
sz = IDENTIFIER_SIZE; sz = IDENTIFIER_SIZE;
MSI_RecordGetStringW(row,1,package->features[index].Feature,&sz); MSI_RecordGetStringW(row,1,feature->Feature,&sz);
TRACE("Loading feature %s\n",debugstr_w(package->features[index].Feature)); TRACE("Loading feature %s\n",debugstr_w(feature->Feature));
sz = IDENTIFIER_SIZE; sz = IDENTIFIER_SIZE;
if (!MSI_RecordIsNull(row,2)) if (!MSI_RecordIsNull(row,2))
MSI_RecordGetStringW(row,2,package->features[index].Feature_Parent,&sz); MSI_RecordGetStringW(row,2,feature->Feature_Parent,&sz);
sz = 0x100; sz = 0x100;
if (!MSI_RecordIsNull(row,3)) if (!MSI_RecordIsNull(row,3))
MSI_RecordGetStringW(row,3,package->features[index].Title,&sz); MSI_RecordGetStringW(row,3,feature->Title,&sz);
sz = 0x100; sz = 0x100;
if (!MSI_RecordIsNull(row,4)) if (!MSI_RecordIsNull(row,4))
MSI_RecordGetStringW(row,4,package->features[index].Description,&sz); MSI_RecordGetStringW(row,4,feature->Description,&sz);
if (!MSI_RecordIsNull(row,5)) if (!MSI_RecordIsNull(row,5))
package->features[index].Display = MSI_RecordGetInteger(row,5); feature->Display = MSI_RecordGetInteger(row,5);
package->features[index].Level= MSI_RecordGetInteger(row,6); feature->Level= MSI_RecordGetInteger(row,6);
sz = IDENTIFIER_SIZE;
if (!MSI_RecordIsNull(row,7))
MSI_RecordGetStringW(row,7,feature->Directory,&sz);
sz = IDENTIFIER_SIZE; feature->Attributes = MSI_RecordGetInteger(row,8);
if (!MSI_RecordIsNull(row,7))
MSI_RecordGetStringW(row,7,package->features[index].Directory,&sz);
package->features[index].Attributes= MSI_RecordGetInteger(row,8); feature->Installed = INSTALLSTATE_ABSENT;
feature->Action = INSTALLSTATE_UNKNOWN;
feature->ActionRequest = INSTALLSTATE_UNKNOWN;
package->features[index].Installed = INSTALLSTATE_ABSENT; list_add_tail( &package->features, &feature->entry );
package->features[index].Action = INSTALLSTATE_UNKNOWN;
package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN;
/* load feature components */ /* load feature components */
rc = MSI_OpenQuery(package->db, &view, Query1, rc = MSI_OpenQuery( package->db, &view, Query1, feature->Feature );
package->features[index].Feature);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS; return ERROR_SUCCESS;
ilfs.package = package;
ilfs.feature = feature;
MSI_IterateRecords(view, NULL, iterate_load_featurecomponents , &ilfs); MSI_IterateRecords(view, NULL, iterate_load_featurecomponents , &ilfs);
msiobj_release(&view->hdr); msiobj_release(&view->hdr);
...@@ -1420,7 +1411,7 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) ...@@ -1420,7 +1411,7 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir)
static void ACTION_UpdateInstallStates(MSIPACKAGE *package) static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
{ {
MSICOMPONENT *comp; MSICOMPONENT *comp;
int i; MSIFEATURE *feature;
LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry ) LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
{ {
...@@ -1432,13 +1423,12 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package) ...@@ -1432,13 +1423,12 @@ static void ACTION_UpdateInstallStates(MSIPACKAGE *package)
comp->Installed = res; comp->Installed = res;
} }
for (i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
ComponentList *cl; ComponentList *cl;
INSTALLSTATE res = -10; INSTALLSTATE res = -10;
LIST_FOR_EACH_ENTRY( cl, package->features[i].Components, LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
ComponentList, entry )
{ {
comp= cl->component; comp= cl->component;
...@@ -1461,19 +1451,19 @@ static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property, ...@@ -1461,19 +1451,19 @@ static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property,
{ {
static const WCHAR all[]={'A','L','L',0}; static const WCHAR all[]={'A','L','L',0};
LPWSTR override = NULL; LPWSTR override = NULL;
INT i;
BOOL rc = FALSE; BOOL rc = FALSE;
MSIFEATURE *feature;
override = load_dynamic_property(package, property, NULL); override = load_dynamic_property(package, property, NULL);
if (override) if (override)
{ {
rc = TRUE; rc = TRUE;
for(i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
if (strcmpiW(override,all)==0) if (strcmpiW(override,all)==0)
{ {
package->features[i].ActionRequest= state; feature->ActionRequest= state;
package->features[i].Action = state; feature->Action = state;
} }
else else
{ {
...@@ -1483,12 +1473,11 @@ static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property, ...@@ -1483,12 +1473,11 @@ static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property,
while (ptr) while (ptr)
{ {
if ((ptr2 && if ((ptr2 &&
strncmpW(ptr,package->features[i].Feature, ptr2-ptr)==0) strncmpW(ptr,feature->Feature, ptr2-ptr)==0)
|| (!ptr2 && || (!ptr2 && strcmpW(ptr,feature->Feature)==0))
strcmpW(ptr,package->features[i].Feature)==0))
{ {
package->features[i].ActionRequest= state; feature->ActionRequest= state;
package->features[i].Action = state; feature->Action = state;
break; break;
} }
if (ptr2) if (ptr2)
...@@ -1511,7 +1500,6 @@ static UINT SetFeatureStates(MSIPACKAGE *package) ...@@ -1511,7 +1500,6 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
{ {
LPWSTR level; LPWSTR level;
INT install_level; INT install_level;
DWORD i;
static const WCHAR szlevel[] = static const WCHAR szlevel[] =
{'I','N','S','T','A','L','L','L','E','V','E','L',0}; {'I','N','S','T','A','L','L','L','E','V','E','L',0};
static const WCHAR szAddLocal[] = static const WCHAR szAddLocal[] =
...@@ -1520,6 +1508,8 @@ static UINT SetFeatureStates(MSIPACKAGE *package) ...@@ -1520,6 +1508,8 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
{'R','E','M','O','V','E',0}; {'R','E','M','O','V','E',0};
BOOL override = FALSE; BOOL override = FALSE;
MSICOMPONENT* component; MSICOMPONENT* component;
MSIFEATURE *feature;
/* I do not know if this is where it should happen.. but */ /* I do not know if this is where it should happen.. but */
...@@ -1561,30 +1551,27 @@ static UINT SetFeatureStates(MSIPACKAGE *package) ...@@ -1561,30 +1551,27 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
if (!override) if (!override)
{ {
for(i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
BOOL feature_state = ((package->features[i].Level > 0) && BOOL feature_state = ((feature->Level > 0) &&
(package->features[i].Level <= install_level)); (feature->Level <= install_level));
if ((feature_state) && if ((feature_state) && (feature->Action == INSTALLSTATE_UNKNOWN))
(package->features[i].Action == INSTALLSTATE_UNKNOWN))
{ {
if (package->features[i].Attributes & if (feature->Attributes & msidbFeatureAttributesFavorSource)
msidbFeatureAttributesFavorSource)
{ {
package->features[i].ActionRequest = INSTALLSTATE_SOURCE; feature->ActionRequest = INSTALLSTATE_SOURCE;
package->features[i].Action = INSTALLSTATE_SOURCE; feature->Action = INSTALLSTATE_SOURCE;
} }
else if (package->features[i].Attributes & else if (feature->Attributes & msidbFeatureAttributesFavorAdvertise)
msidbFeatureAttributesFavorAdvertise)
{ {
package->features[i].ActionRequest =INSTALLSTATE_ADVERTISED; feature->ActionRequest = INSTALLSTATE_ADVERTISED;
package->features[i].Action =INSTALLSTATE_ADVERTISED; feature->Action = INSTALLSTATE_ADVERTISED;
} }
else else
{ {
package->features[i].ActionRequest = INSTALLSTATE_LOCAL; feature->ActionRequest = INSTALLSTATE_LOCAL;
package->features[i].Action = INSTALLSTATE_LOCAL; feature->Action = INSTALLSTATE_LOCAL;
} }
} }
} }
...@@ -1602,16 +1589,15 @@ static UINT SetFeatureStates(MSIPACKAGE *package) ...@@ -1602,16 +1589,15 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
* now we want to enable or disable components base on feature * now we want to enable or disable components base on feature
*/ */
for(i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
MSIFEATURE* feature = &package->features[i];
ComponentList *cl; ComponentList *cl;
TRACE("Examining Feature %s (Installed %i, Action %i, Request %i)\n", TRACE("Examining Feature %s (Installed %i, Action %i, Request %i)\n",
debugstr_w(feature->Feature), feature->Installed, feature->Action, debugstr_w(feature->Feature), feature->Installed, feature->Action,
feature->ActionRequest); feature->ActionRequest);
LIST_FOR_EACH_ENTRY( cl, feature->Components, ComponentList, entry ) LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{ {
component = cl->component; component = cl->component;
...@@ -1692,14 +1678,14 @@ static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param) ...@@ -1692,14 +1678,14 @@ static UINT ITERATE_CostFinalizeDirectories(MSIRECORD *row, LPVOID param)
static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param) static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
{ {
MSIPACKAGE *package = (MSIPACKAGE*)param; MSIPACKAGE *package = (MSIPACKAGE*)param;
LPCWSTR Feature; LPCWSTR name;
int feature_index; MSIFEATURE *feature;
Feature = MSI_RecordGetString(row,1); name = MSI_RecordGetString( row, 1 );
feature_index = get_loaded_feature(package,Feature); feature = get_loaded_feature( package, name );
if (feature_index < 0) if (!feature)
ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature)); ERR("FAILED to find loaded feature %s\n",debugstr_w(name));
else else
{ {
LPCWSTR Condition; LPCWSTR Condition;
...@@ -1708,9 +1694,8 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param) ...@@ -1708,9 +1694,8 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
if (MSI_EvaluateConditionW(package,Condition) == MSICONDITION_TRUE) if (MSI_EvaluateConditionW(package,Condition) == MSICONDITION_TRUE)
{ {
int level = MSI_RecordGetInteger(row,2); int level = MSI_RecordGetInteger(row,2);
TRACE("Reseting feature %s to level %i\n", debugstr_w(Feature), TRACE("Reseting feature %s to level %i\n", debugstr_w(name), level);
level); feature->Level = level;
package->features[feature_index].Level = level;
} }
} }
return ERROR_SUCCESS; return ERROR_SUCCESS;
...@@ -2212,6 +2197,7 @@ static UINT ACTION_InstallValidate(MSIPACKAGE *package) ...@@ -2212,6 +2197,7 @@ static UINT ACTION_InstallValidate(MSIPACKAGE *package)
UINT rc; UINT rc;
MSIQUERY * view; MSIQUERY * view;
MSIRECORD * row = 0; MSIRECORD * row = 0;
MSIFEATURE *feature;
int i; int i;
TRACE(" InstallValidate \n"); TRACE(" InstallValidate \n");
...@@ -2251,9 +2237,8 @@ static UINT ACTION_InstallValidate(MSIPACKAGE *package) ...@@ -2251,9 +2237,8 @@ static UINT ACTION_InstallValidate(MSIPACKAGE *package)
total += package->files[i].FileSize; total += package->files[i].FileSize;
ui_progress(package,0,total,0,0); ui_progress(package,0,total,0,0);
for(i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
MSIFEATURE* feature = &package->features[i];
TRACE("Feature: %s; Installed: %i; Action %i; Request %i\n", TRACE("Feature: %s; Installed: %i; Action %i; Request %i\n",
debugstr_w(feature->Feature), feature->Installed, feature->Action, debugstr_w(feature->Feature), feature->Installed, feature->Action,
feature->ActionRequest); feature->ActionRequest);
...@@ -2423,6 +2408,7 @@ static UINT ACTION_WriteSharedDLLsCount(LPCWSTR path, UINT count) ...@@ -2423,6 +2408,7 @@ static UINT ACTION_WriteSharedDLLsCount(LPCWSTR path, UINT count)
*/ */
static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp ) static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp )
{ {
MSIFEATURE *feature;
INT count = 0; INT count = 0;
BOOL write = FALSE; BOOL write = FALSE;
INT j; INT j;
...@@ -2442,30 +2428,28 @@ static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp ) ...@@ -2442,30 +2428,28 @@ static void ACTION_RefCountComponent( MSIPACKAGE* package, MSICOMPONENT *comp )
} }
/* increment counts */ /* increment counts */
for (j = 0; j < package->loaded_features; j++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
ComponentList *cl; ComponentList *cl;
if (!ACTION_VerifyFeatureForAction(package,j,INSTALLSTATE_LOCAL)) if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ))
continue; continue;
LIST_FOR_EACH_ENTRY( cl, package->features[j].Components, LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
ComponentList, entry )
{ {
if ( cl->component == comp ) if ( cl->component == comp )
count++; count++;
} }
} }
/* decrement counts */ /* decrement counts */
for (j = 0; j < package->loaded_features; j++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
ComponentList *cl; ComponentList *cl;
if (!ACTION_VerifyFeatureForAction(package,j,INSTALLSTATE_ABSENT)) if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ABSENT ))
continue; continue;
LIST_FOR_EACH_ENTRY( cl, package->features[j].Components, LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
ComponentList, entry )
{ {
if ( cl->component == comp ) if ( cl->component == comp )
count--; count--;
...@@ -3310,8 +3294,8 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package) ...@@ -3310,8 +3294,8 @@ static UINT ACTION_SelfRegModules(MSIPACKAGE *package)
static UINT ACTION_PublishFeatures(MSIPACKAGE *package) static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
{ {
MSIFEATURE *feature;
UINT rc; UINT rc;
DWORD i;
HKEY hkey=0; HKEY hkey=0;
HKEY hukey=0; HKEY hukey=0;
...@@ -3327,7 +3311,7 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) ...@@ -3327,7 +3311,7 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
goto end; goto end;
/* here the guids are base 85 encoded */ /* here the guids are base 85 encoded */
for (i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
ComponentList *cl; ComponentList *cl;
LPWSTR data = NULL; LPWSTR data = NULL;
...@@ -3335,25 +3319,23 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) ...@@ -3335,25 +3319,23 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
INT size; INT size;
BOOL absent = FALSE; BOOL absent = FALSE;
if (!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_LOCAL) && if (!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL ) &&
!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_SOURCE) && !ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_SOURCE ) &&
!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_ADVERTISED)) !ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED ))
absent = TRUE; absent = TRUE;
size = 1; size = 1;
LIST_FOR_EACH_ENTRY( cl, package->features[i].Components, LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
ComponentList, entry )
{ {
size += 21; size += 21;
} }
if (package->features[i].Feature_Parent[0]) if (feature->Feature_Parent[0])
size += strlenW(package->features[i].Feature_Parent)+2; size += strlenW( feature->Feature_Parent )+2;
data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); data = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
data[0] = 0; data[0] = 0;
LIST_FOR_EACH_ENTRY( cl, package->features[i].Components, LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
ComponentList, entry )
{ {
MSICOMPONENT* component = cl->component; MSICOMPONENT* component = cl->component;
WCHAR buf[21]; WCHAR buf[21];
...@@ -3368,32 +3350,30 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) ...@@ -3368,32 +3350,30 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
strcatW(data,buf); strcatW(data,buf);
} }
} }
if (package->features[i].Feature_Parent[0]) if (feature->Feature_Parent[0])
{ {
static const WCHAR sep[] = {'\2',0}; static const WCHAR sep[] = {'\2',0};
strcatW(data,sep); strcatW(data,sep);
strcatW(data,package->features[i].Feature_Parent); strcatW(data,feature->Feature_Parent);
} }
size = (strlenW(data)+1)*sizeof(WCHAR); size = (strlenW(data)+1)*sizeof(WCHAR);
RegSetValueExW(hkey,package->features[i].Feature,0,REG_SZ, RegSetValueExW( hkey, feature->Feature, 0, REG_SZ, (LPBYTE)data,size );
(LPBYTE)data,size);
HeapFree(GetProcessHeap(),0,data); HeapFree(GetProcessHeap(),0,data);
if (!absent) if (!absent)
{ {
size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR); size = strlenW(feature->Feature_Parent)*sizeof(WCHAR);
RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ, RegSetValueExW(hukey,feature->Feature,0,REG_SZ,
(LPBYTE)package->features[i].Feature_Parent,size); (LPBYTE)feature->Feature_Parent,size);
} }
else else
{ {
size = (strlenW(package->features[i].Feature_Parent)+2)* size = (strlenW(feature->Feature_Parent)+2)* sizeof(WCHAR);
sizeof(WCHAR);
data = HeapAlloc(GetProcessHeap(),0,size); data = HeapAlloc(GetProcessHeap(),0,size);
data[0] = 0x6; data[0] = 0x6;
strcpyW(&data[1],package->features[i].Feature_Parent); strcpyW( &data[1], feature->Feature_Parent );
RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ, RegSetValueExW(hukey,feature->Feature,0,REG_SZ,
(LPBYTE)data,size); (LPBYTE)data,size);
HeapFree(GetProcessHeap(),0,data); HeapFree(GetProcessHeap(),0,data);
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
typedef struct tagMSIFEATURE typedef struct tagMSIFEATURE
{ {
struct list entry;
WCHAR Feature[IDENTIFIER_SIZE]; WCHAR Feature[IDENTIFIER_SIZE];
WCHAR Feature_Parent[IDENTIFIER_SIZE]; WCHAR Feature_Parent[IDENTIFIER_SIZE];
WCHAR Title[0x100]; WCHAR Title[0x100];
...@@ -37,7 +38,7 @@ typedef struct tagMSIFEATURE ...@@ -37,7 +38,7 @@ typedef struct tagMSIFEATURE
INSTALLSTATE ActionRequest; INSTALLSTATE ActionRequest;
INSTALLSTATE Action; INSTALLSTATE Action;
struct list *Components; struct list Components;
INT Cost; INT Cost;
} MSIFEATURE; } MSIFEATURE;
...@@ -127,7 +128,7 @@ typedef struct tagMSICLASS ...@@ -127,7 +128,7 @@ typedef struct tagMSICLASS
LPWSTR DefInprocHandler; LPWSTR DefInprocHandler;
LPWSTR DefInprocHandler32; LPWSTR DefInprocHandler32;
LPWSTR Argument; LPWSTR Argument;
INT FeatureIndex; MSIFEATURE *Feature;
INT Attributes; INT Attributes;
/* not in the table, set during installation */ /* not in the table, set during installation */
BOOL Installed; BOOL Installed;
...@@ -140,7 +141,7 @@ typedef struct tagMSIEXTENSION ...@@ -140,7 +141,7 @@ typedef struct tagMSIEXTENSION
INT ProgIDIndex; INT ProgIDIndex;
LPWSTR ProgIDText; LPWSTR ProgIDText;
INT MIMEIndex; INT MIMEIndex;
INT FeatureIndex; MSIFEATURE *Feature;
/* not in the table, set during installation */ /* not in the table, set during installation */
BOOL Installed; BOOL Installed;
INT VerbCount; INT VerbCount;
...@@ -236,7 +237,7 @@ LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc); ...@@ -236,7 +237,7 @@ LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc);
LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
BOOL set_prop, MSIFOLDER **folder); BOOL set_prop, MSIFOLDER **folder);
MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component ); MSICOMPONENT *get_loaded_component( MSIPACKAGE* package, LPCWSTR Component );
int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature ); MSIFEATURE *get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature );
int get_loaded_file(MSIPACKAGE* package, LPCWSTR file); int get_loaded_file(MSIPACKAGE* package, LPCWSTR file);
int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path); int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action); UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action);
...@@ -245,7 +246,7 @@ DWORD build_version_dword(LPCWSTR); ...@@ -245,7 +246,7 @@ DWORD build_version_dword(LPCWSTR);
LPWSTR build_directory_name(DWORD , ...); LPWSTR build_directory_name(DWORD , ...);
BOOL create_full_pathW(const WCHAR *path); BOOL create_full_pathW(const WCHAR *path);
BOOL ACTION_VerifyComponentForAction(MSIPACKAGE*, MSICOMPONENT*, INSTALLSTATE); BOOL ACTION_VerifyComponentForAction(MSIPACKAGE*, MSICOMPONENT*, INSTALLSTATE);
BOOL ACTION_VerifyFeatureForAction(MSIPACKAGE*, INT, INSTALLSTATE); BOOL ACTION_VerifyFeatureForAction(MSIFEATURE*, INSTALLSTATE);
void reduce_to_longfilename(WCHAR*); void reduce_to_longfilename(WCHAR*);
void reduce_to_shortfilename(WCHAR*); void reduce_to_shortfilename(WCHAR*);
LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR); LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
......
...@@ -329,7 +329,7 @@ static INT load_class(MSIPACKAGE* package, MSIRECORD *row) ...@@ -329,7 +329,7 @@ static INT load_class(MSIPACKAGE* package, MSIRECORD *row)
deformat_string(package,buffer,&package->classes[index].Argument); deformat_string(package,buffer,&package->classes[index].Argument);
buffer = MSI_RecordGetString(row,12); buffer = MSI_RecordGetString(row,12);
package->classes[index].FeatureIndex = get_loaded_feature(package,buffer); package->classes[index].Feature = get_loaded_feature(package,buffer);
package->classes[index].Attributes = MSI_RecordGetInteger(row,13); package->classes[index].Attributes = MSI_RecordGetInteger(row,13);
...@@ -475,8 +475,7 @@ static INT load_extension(MSIPACKAGE* package, MSIRECORD *row) ...@@ -475,8 +475,7 @@ static INT load_extension(MSIPACKAGE* package, MSIRECORD *row)
package->extensions[index].MIMEIndex = load_given_mime(package,buffer); package->extensions[index].MIMEIndex = load_given_mime(package,buffer);
buffer = MSI_RecordGetString(row,5); buffer = MSI_RecordGetString(row,5);
package->extensions[index].FeatureIndex = package->extensions[index].Feature = get_loaded_feature(package,buffer);
get_loaded_feature(package,buffer);
return index; return index;
} }
...@@ -919,28 +918,28 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package) ...@@ -919,28 +918,28 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
for (i = 0; i < package->loaded_classes; i++) for (i = 0; i < package->loaded_classes; i++)
{ {
MSICOMPONENT *comp; MSICOMPONENT *comp;
INT index, f_index; INT index;
DWORD size, sz; DWORD size, sz;
LPWSTR argument; LPWSTR argument;
MSIFEATURE *feature;
comp = package->classes[i].Component; comp = package->classes[i].Component;
if ( !comp ) if ( !comp )
continue; continue;
f_index = package->classes[i].FeatureIndex; feature = package->classes[i].Feature;
/* /*
* yes. MSDN says that these are based on _Feature_ not on * yes. MSDN says that these are based on _Feature_ not on
* Component. So verify the feature is to be installed * Component. So verify the feature is to be installed
*/ */
if ((!ACTION_VerifyFeatureForAction(package, f_index, if ((!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL )) &&
INSTALLSTATE_LOCAL)) && !(install_on_demand &&
!(install_on_demand && ACTION_VerifyFeatureForAction(package, ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED )))
f_index, INSTALLSTATE_ADVERTISED)))
{ {
TRACE("Skipping class %s reg due to disabled feature %s\n", TRACE("Skipping class %s reg due to disabled feature %s\n",
debugstr_w(package->classes[i].CLSID), debugstr_w(package->classes[i].CLSID),
debugstr_w(package->features[f_index].Feature)); debugstr_w(feature->Feature));
continue; continue;
} }
...@@ -1347,12 +1346,12 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid, ...@@ -1347,12 +1346,12 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
HeapFree(GetProcessHeap(),0,command); HeapFree(GetProcessHeap(),0,command);
advertise = create_component_advertise_string(package, component, advertise = create_component_advertise_string(package, component,
package->features[extension->FeatureIndex].Feature); extension->Feature->Feature);
size = strlenW(advertise); size = strlenW(advertise);
if (verb->Argument) if (verb->Argument)
size += strlenW(verb->Argument); size += strlenW(verb->Argument);
size += 4; size += 4;
command = HeapAlloc(GetProcessHeap(),0, size * sizeof (WCHAR)); command = HeapAlloc(GetProcessHeap(),0, size * sizeof (WCHAR));
...@@ -1361,7 +1360,7 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid, ...@@ -1361,7 +1360,7 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
strcpyW(command,advertise); strcpyW(command,advertise);
if (verb->Argument) if (verb->Argument)
{ {
static const WCHAR szSpace[] = {' ',0}; static const WCHAR szSpace[] = {' ',0};
strcatW(command,szSpace); strcatW(command,szSpace);
strcatW(command,verb->Argument); strcatW(command,verb->Argument);
} }
...@@ -1422,25 +1421,24 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package) ...@@ -1422,25 +1421,24 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
for (i = 0; i < package->loaded_extensions; i++) for (i = 0; i < package->loaded_extensions; i++)
{ {
WCHAR extension[257]; WCHAR extension[257];
INT f_index; MSIFEATURE *feature;
if (!package->extensions[i].Component) if (!package->extensions[i].Component)
continue; continue;
f_index = package->extensions[i].FeatureIndex; feature = package->extensions[i].Feature;
/* /*
* yes. MSDN says that these are based on _Feature_ not on * yes. MSDN says that these are based on _Feature_ not on
* Component. So verify the feature is to be installed * Component. So verify the feature is to be installed
*/ */
if ((!ACTION_VerifyFeatureForAction(package, f_index, if ((!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL )) &&
INSTALLSTATE_LOCAL)) && !(install_on_demand &&
!(install_on_demand && ACTION_VerifyFeatureForAction(package, ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED )))
f_index, INSTALLSTATE_ADVERTISED)))
{ {
TRACE("Skipping extension %s reg due to disabled feature %s\n", TRACE("Skipping extension %s reg due to disabled feature %s\n",
debugstr_w(package->extensions[i].Extension), debugstr_w(package->extensions[i].Extension),
debugstr_w(package->features[f_index].Feature)); debugstr_w(feature->Feature));
continue; continue;
} }
......
...@@ -170,7 +170,7 @@ static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument, ...@@ -170,7 +170,7 @@ static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog) msi_dialog* dialog)
{ {
static const WCHAR szAll[] = {'A','L','L',0}; static const WCHAR szAll[] = {'A','L','L',0};
int i; MSIFEATURE *feature = NULL;
if (lstrcmpW(szAll,argument)) if (lstrcmpW(szAll,argument))
{ {
...@@ -178,10 +178,10 @@ static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument, ...@@ -178,10 +178,10 @@ static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,
} }
else else
{ {
for (i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
package->features[i].ActionRequest = INSTALLSTATE_LOCAL; feature->ActionRequest = INSTALLSTATE_LOCAL;
package->features[i].Action = INSTALLSTATE_LOCAL; feature->Action = INSTALLSTATE_LOCAL;
} }
ACTION_UpdateComponentStates(package,argument); ACTION_UpdateComponentStates(package,argument);
} }
...@@ -192,7 +192,7 @@ static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument, ...@@ -192,7 +192,7 @@ static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog) msi_dialog* dialog)
{ {
static const WCHAR szAll[] = {'A','L','L',0}; static const WCHAR szAll[] = {'A','L','L',0};
int i; MSIFEATURE *feature = NULL;
if (lstrcmpW(szAll,argument)) if (lstrcmpW(szAll,argument))
{ {
...@@ -200,10 +200,10 @@ static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument, ...@@ -200,10 +200,10 @@ static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument,
} }
else else
{ {
for (i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
package->features[i].ActionRequest = INSTALLSTATE_ABSENT; feature->ActionRequest = INSTALLSTATE_ABSENT;
package->features[i].Action= INSTALLSTATE_ABSENT; feature->Action= INSTALLSTATE_ABSENT;
} }
ACTION_UpdateComponentStates(package,argument); ACTION_UpdateComponentStates(package,argument);
} }
...@@ -214,7 +214,7 @@ static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument, ...@@ -214,7 +214,7 @@ static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog) msi_dialog* dialog)
{ {
static const WCHAR szAll[] = {'A','L','L',0}; static const WCHAR szAll[] = {'A','L','L',0};
int i; MSIFEATURE *feature = NULL;
if (lstrcmpW(szAll,argument)) if (lstrcmpW(szAll,argument))
{ {
...@@ -222,10 +222,10 @@ static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument, ...@@ -222,10 +222,10 @@ static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument,
} }
else else
{ {
for (i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
package->features[i].ActionRequest = INSTALLSTATE_SOURCE; feature->ActionRequest = INSTALLSTATE_SOURCE;
package->features[i].Action = INSTALLSTATE_SOURCE; feature->Action = INSTALLSTATE_SOURCE;
} }
ACTION_UpdateComponentStates(package,argument); ACTION_UpdateComponentStates(package,argument);
} }
......
...@@ -179,20 +179,16 @@ MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component ) ...@@ -179,20 +179,16 @@ MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component )
return NULL; return NULL;
} }
int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature ) MSIFEATURE* get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
{ {
int rc = -1; MSIFEATURE *feature = NULL;
DWORD i;
for (i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{ {
if (strcmpW(Feature,package->features[i].Feature)==0) if (lstrcmpW( Feature, feature->Feature )==0)
{ return feature;
rc = i;
break;
}
} }
return rc; return NULL;
} }
int get_loaded_file(MSIPACKAGE* package, LPCWSTR file) int get_loaded_file(MSIPACKAGE* package, LPCWSTR file)
...@@ -449,6 +445,20 @@ static void remove_tracked_tempfiles(MSIPACKAGE* package) ...@@ -449,6 +445,20 @@ static void remove_tracked_tempfiles(MSIPACKAGE* package)
} }
} }
static void free_feature( MSIFEATURE *feature )
{
struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &feature->Components )
{
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
list_remove( &cl->entry );
HeapFree( GetProcessHeap(), 0, cl );
}
HeapFree( GetProcessHeap(), 0, feature );
}
/* Called when the package is being closed */ /* Called when the package is being closed */
void ACTION_free_package_structures( MSIPACKAGE* package) void ACTION_free_package_structures( MSIPACKAGE* package)
{ {
...@@ -459,16 +469,11 @@ void ACTION_free_package_structures( MSIPACKAGE* package) ...@@ -459,16 +469,11 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
remove_tracked_tempfiles(package); remove_tracked_tempfiles(package);
if (package->features) LIST_FOR_EACH_SAFE( item, cursor, &package->features )
{ {
LIST_FOR_EACH_SAFE( item, cursor, package->features->Components ) MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
{ list_remove( &feature->entry );
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry ); free_feature( feature );
list_remove( &cl->entry );
HeapFree(GetProcessHeap(), 0, cl);
}
HeapFree(GetProcessHeap(),0,package->features->Components);
HeapFree(GetProcessHeap(),0,package->features);
} }
for (i = 0; i < package->loaded_folders; i++) for (i = 0; i < package->loaded_folders; i++)
...@@ -773,13 +778,12 @@ BOOL ACTION_VerifyComponentForAction(MSIPACKAGE* package, MSICOMPONENT* comp, ...@@ -773,13 +778,12 @@ BOOL ACTION_VerifyComponentForAction(MSIPACKAGE* package, MSICOMPONENT* comp,
return FALSE; return FALSE;
} }
BOOL ACTION_VerifyFeatureForAction(MSIPACKAGE* package, INT index, BOOL ACTION_VerifyFeatureForAction( MSIFEATURE* feature, INSTALLSTATE check )
INSTALLSTATE check )
{ {
if (package->features[index].Installed == check) if (feature->Installed == check)
return FALSE; return FALSE;
if (package->features[index].ActionRequest == check) if (feature->ActionRequest == check)
return TRUE; return TRUE;
else else
return FALSE; return FALSE;
...@@ -852,19 +856,17 @@ LPWSTR create_component_advertise_string(MSIPACKAGE* package, ...@@ -852,19 +856,17 @@ LPWSTR create_component_advertise_string(MSIPACKAGE* package,
/* update compoennt state based on a feature change */ /* update compoennt state based on a feature change */
void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature) void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
{ {
int i;
INSTALLSTATE newstate; INSTALLSTATE newstate;
MSIFEATURE *feature; MSIFEATURE *feature;
ComponentList *cl; ComponentList *cl;
i = get_loaded_feature(package,szFeature); feature = get_loaded_feature(package,szFeature);
if (i < 0) if (!feature)
return; return;
feature = &package->features[i];
newstate = feature->ActionRequest; newstate = feature->ActionRequest;
LIST_FOR_EACH_ENTRY( cl, feature->Components, ComponentList, entry ) LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry )
{ {
MSICOMPONENT* component = cl->component; MSICOMPONENT* component = cl->component;
...@@ -883,27 +885,25 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature) ...@@ -883,27 +885,25 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
} }
else else
{ {
int j;
ComponentList *clist; ComponentList *clist;
MSIFEATURE *f;
component->ActionRequest = newstate; component->ActionRequest = newstate;
component->Action = newstate; component->Action = newstate;
/*if any other feature wants is local we need to set it local*/ /*if any other feature wants is local we need to set it local*/
for (j = 0; LIST_FOR_EACH_ENTRY( f, &package->features, MSIFEATURE, entry )
j < package->loaded_features &&
component->ActionRequest != INSTALLSTATE_LOCAL;
j++)
{ {
LIST_FOR_EACH_ENTRY( clist, package->features[j].Components, if ( component->ActionRequest != INSTALLSTATE_LOCAL )
ComponentList, entry ) break;
LIST_FOR_EACH_ENTRY( clist, &f->Components, ComponentList, entry )
{ {
if ( clist->component == cl->component ) if ( clist->component == component )
{ {
if (package->features[j].ActionRequest == if (f->ActionRequest == INSTALLSTATE_LOCAL)
INSTALLSTATE_LOCAL)
{ {
TRACE("Saved by %s\n", debugstr_w(package->features[j].Feature)); TRACE("Saved by %s\n", debugstr_w(f->Feature));
component->ActionRequest = INSTALLSTATE_LOCAL; component->ActionRequest = INSTALLSTATE_LOCAL;
component->Action = INSTALLSTATE_LOCAL; component->Action = INSTALLSTATE_LOCAL;
} }
......
...@@ -416,30 +416,29 @@ UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature, ...@@ -416,30 +416,29 @@ UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature, UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
INSTALLSTATE iState) INSTALLSTATE iState)
{ {
INT index, i;
UINT rc = ERROR_SUCCESS; UINT rc = ERROR_SUCCESS;
MSIFEATURE *feature, *child;
TRACE(" %s to %i\n",debugstr_w(szFeature), iState); TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
index = get_loaded_feature(package,szFeature); feature = get_loaded_feature(package,szFeature);
if (index < 0) if (!feature)
return ERROR_UNKNOWN_FEATURE; return ERROR_UNKNOWN_FEATURE;
if (iState == INSTALLSTATE_ADVERTISED && if (iState == INSTALLSTATE_ADVERTISED &&
package->features[index].Attributes & feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
msidbFeatureAttributesDisallowAdvertise)
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
package->features[index].ActionRequest= iState; feature->ActionRequest = iState;
package->features[index].Action= iState; feature->Action = iState;
ACTION_UpdateComponentStates(package,szFeature); ACTION_UpdateComponentStates(package,szFeature);
/* update all the features that are children of this feature */ /* update all the features that are children of this feature */
for (i = 0; i < package->loaded_features; i++) LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
{ {
if (strcmpW(szFeature, package->features[i].Feature_Parent) == 0) if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
MSI_SetFeatureStateW(package, package->features[i].Feature, iState); MSI_SetFeatureStateW(package, child->Feature, iState);
} }
return rc; return rc;
...@@ -487,19 +486,19 @@ UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature, ...@@ -487,19 +486,19 @@ UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature, UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
INSTALLSTATE *piInstalled, INSTALLSTATE *piAction) INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{ {
INT index; MSIFEATURE *feature;
index = get_loaded_feature(package,szFeature); feature = get_loaded_feature(package,szFeature);
if (index < 0) if (!feature)
return ERROR_UNKNOWN_FEATURE; return ERROR_UNKNOWN_FEATURE;
if (piInstalled) if (piInstalled)
*piInstalled = package->features[index].Installed; *piInstalled = feature->Installed;
if (piAction) if (piAction)
*piAction = package->features[index].Action; *piAction = feature->Action;
TRACE("returning %i %i\n",*piInstalled,*piAction); TRACE("returning %i %i\n", feature->Installed, feature->Action);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
...@@ -547,8 +546,8 @@ UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent, ...@@ -547,8 +546,8 @@ UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
{ {
MSICOMPONENT *comp; MSICOMPONENT *comp;
TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled, TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
piAction); piInstalled, piAction);
comp = get_loaded_component(package,szComponent); comp = get_loaded_component(package,szComponent);
if (!comp) if (!comp)
...@@ -560,8 +559,7 @@ piAction); ...@@ -560,8 +559,7 @@ piAction);
if (piAction) if (piAction)
*piAction = comp->Action; *piAction = comp->Action;
TRACE("states (%i, %i)\n", TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
(piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
......
...@@ -186,11 +186,10 @@ typedef struct tagMSIPACKAGE ...@@ -186,11 +186,10 @@ typedef struct tagMSIPACKAGE
{ {
MSIOBJECTHDR hdr; MSIOBJECTHDR hdr;
MSIDATABASE *db; MSIDATABASE *db;
struct tagMSIFEATURE *features;
UINT loaded_features;
struct tagMSIFOLDER *folders; struct tagMSIFOLDER *folders;
UINT loaded_folders; UINT loaded_folders;
struct list components; struct list components;
struct list features;
struct tagMSIFILE *files; struct tagMSIFILE *files;
UINT loaded_files; UINT loaded_files;
LPWSTR ActionFormat; LPWSTR ActionFormat;
......
...@@ -377,11 +377,10 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db ) ...@@ -377,11 +377,10 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
msiobj_addref( &db->hdr ); msiobj_addref( &db->hdr );
package->db = db; package->db = db;
package->features = NULL; list_init( &package->features );
package->folders = NULL; package->folders = NULL;
list_init( &package->components ); list_init( &package->components );
package->files = NULL; package->files = NULL;
package->loaded_features = 0;
package->loaded_folders = 0; package->loaded_folders = 0;
package->loaded_files = 0; package->loaded_files = 0;
package->ActionFormat = NULL; package->ActionFormat = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment