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
......@@ -24,6 +24,7 @@
typedef struct tagMSIFEATURE
{
struct list entry;
WCHAR Feature[IDENTIFIER_SIZE];
WCHAR Feature_Parent[IDENTIFIER_SIZE];
WCHAR Title[0x100];
......@@ -37,7 +38,7 @@ typedef struct tagMSIFEATURE
INSTALLSTATE ActionRequest;
INSTALLSTATE Action;
struct list *Components;
struct list Components;
INT Cost;
} MSIFEATURE;
......@@ -127,7 +128,7 @@ typedef struct tagMSICLASS
LPWSTR DefInprocHandler;
LPWSTR DefInprocHandler32;
LPWSTR Argument;
INT FeatureIndex;
MSIFEATURE *Feature;
INT Attributes;
/* not in the table, set during installation */
BOOL Installed;
......@@ -140,7 +141,7 @@ typedef struct tagMSIEXTENSION
INT ProgIDIndex;
LPWSTR ProgIDText;
INT MIMEIndex;
INT FeatureIndex;
MSIFEATURE *Feature;
/* not in the table, set during installation */
BOOL Installed;
INT VerbCount;
......@@ -236,7 +237,7 @@ LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, UINT* rc);
LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
BOOL set_prop, MSIFOLDER **folder);
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 track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action);
......@@ -245,7 +246,7 @@ DWORD build_version_dword(LPCWSTR);
LPWSTR build_directory_name(DWORD , ...);
BOOL create_full_pathW(const WCHAR *path);
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_shortfilename(WCHAR*);
LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
......
......@@ -329,7 +329,7 @@ static INT load_class(MSIPACKAGE* package, MSIRECORD *row)
deformat_string(package,buffer,&package->classes[index].Argument);
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);
......@@ -475,8 +475,7 @@ static INT load_extension(MSIPACKAGE* package, MSIRECORD *row)
package->extensions[index].MIMEIndex = load_given_mime(package,buffer);
buffer = MSI_RecordGetString(row,5);
package->extensions[index].FeatureIndex =
get_loaded_feature(package,buffer);
package->extensions[index].Feature = get_loaded_feature(package,buffer);
return index;
}
......@@ -919,28 +918,28 @@ UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
for (i = 0; i < package->loaded_classes; i++)
{
MSICOMPONENT *comp;
INT index, f_index;
INT index;
DWORD size, sz;
LPWSTR argument;
MSIFEATURE *feature;
comp = package->classes[i].Component;
if ( !comp )
continue;
f_index = package->classes[i].FeatureIndex;
feature = package->classes[i].Feature;
/*
* yes. MSDN says that these are based on _Feature_ not on
* Component. So verify the feature is to be installed
*/
if ((!ACTION_VerifyFeatureForAction(package, f_index,
INSTALLSTATE_LOCAL)) &&
!(install_on_demand && ACTION_VerifyFeatureForAction(package,
f_index, INSTALLSTATE_ADVERTISED)))
if ((!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL )) &&
!(install_on_demand &&
ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED )))
{
TRACE("Skipping class %s reg due to disabled feature %s\n",
debugstr_w(package->classes[i].CLSID),
debugstr_w(package->features[f_index].Feature));
debugstr_w(feature->Feature));
continue;
}
......@@ -1347,12 +1346,12 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
HeapFree(GetProcessHeap(),0,command);
advertise = create_component_advertise_string(package, component,
package->features[extension->FeatureIndex].Feature);
extension->Feature->Feature);
size = strlenW(advertise);
if (verb->Argument)
size += strlenW(verb->Argument);
size += strlenW(verb->Argument);
size += 4;
command = HeapAlloc(GetProcessHeap(),0, size * sizeof (WCHAR));
......@@ -1361,7 +1360,7 @@ static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
strcpyW(command,advertise);
if (verb->Argument)
{
static const WCHAR szSpace[] = {' ',0};
static const WCHAR szSpace[] = {' ',0};
strcatW(command,szSpace);
strcatW(command,verb->Argument);
}
......@@ -1422,25 +1421,24 @@ UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
for (i = 0; i < package->loaded_extensions; i++)
{
WCHAR extension[257];
INT f_index;
MSIFEATURE *feature;
if (!package->extensions[i].Component)
continue;
f_index = package->extensions[i].FeatureIndex;
feature = package->extensions[i].Feature;
/*
* yes. MSDN says that these are based on _Feature_ not on
* Component. So verify the feature is to be installed
*/
if ((!ACTION_VerifyFeatureForAction(package, f_index,
INSTALLSTATE_LOCAL)) &&
!(install_on_demand && ACTION_VerifyFeatureForAction(package,
f_index, INSTALLSTATE_ADVERTISED)))
if ((!ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_LOCAL )) &&
!(install_on_demand &&
ACTION_VerifyFeatureForAction( feature, INSTALLSTATE_ADVERTISED )))
{
TRACE("Skipping extension %s reg due to disabled feature %s\n",
debugstr_w(package->extensions[i].Extension),
debugstr_w(package->features[f_index].Feature));
debugstr_w(feature->Feature));
continue;
}
......
......@@ -170,7 +170,7 @@ static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog)
{
static const WCHAR szAll[] = {'A','L','L',0};
int i;
MSIFEATURE *feature = NULL;
if (lstrcmpW(szAll,argument))
{
......@@ -178,10 +178,10 @@ static UINT ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,
}
else
{
for (i = 0; i < package->loaded_features; i++)
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
package->features[i].Action = INSTALLSTATE_LOCAL;
feature->ActionRequest = INSTALLSTATE_LOCAL;
feature->Action = INSTALLSTATE_LOCAL;
}
ACTION_UpdateComponentStates(package,argument);
}
......@@ -192,7 +192,7 @@ static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog)
{
static const WCHAR szAll[] = {'A','L','L',0};
int i;
MSIFEATURE *feature = NULL;
if (lstrcmpW(szAll,argument))
{
......@@ -200,10 +200,10 @@ static UINT ControlEvent_Remove(MSIPACKAGE* package, LPCWSTR argument,
}
else
{
for (i = 0; i < package->loaded_features; i++)
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
package->features[i].ActionRequest = INSTALLSTATE_ABSENT;
package->features[i].Action= INSTALLSTATE_ABSENT;
feature->ActionRequest = INSTALLSTATE_ABSENT;
feature->Action= INSTALLSTATE_ABSENT;
}
ACTION_UpdateComponentStates(package,argument);
}
......@@ -214,7 +214,7 @@ static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog)
{
static const WCHAR szAll[] = {'A','L','L',0};
int i;
MSIFEATURE *feature = NULL;
if (lstrcmpW(szAll,argument))
{
......@@ -222,10 +222,10 @@ static UINT ControlEvent_AddSource(MSIPACKAGE* package, LPCWSTR argument,
}
else
{
for (i = 0; i < package->loaded_features; i++)
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
{
package->features[i].ActionRequest = INSTALLSTATE_SOURCE;
package->features[i].Action = INSTALLSTATE_SOURCE;
feature->ActionRequest = INSTALLSTATE_SOURCE;
feature->Action = INSTALLSTATE_SOURCE;
}
ACTION_UpdateComponentStates(package,argument);
}
......
......@@ -179,20 +179,16 @@ MSICOMPONENT* get_loaded_component( MSIPACKAGE* package, LPCWSTR Component )
return NULL;
}
int get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
MSIFEATURE* get_loaded_feature(MSIPACKAGE* package, LPCWSTR Feature )
{
int rc = -1;
DWORD i;
MSIFEATURE *feature = NULL;
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)
{
rc = i;
break;
}
if (lstrcmpW( Feature, feature->Feature )==0)
return feature;
}
return rc;
return NULL;
}
int get_loaded_file(MSIPACKAGE* package, LPCWSTR file)
......@@ -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 */
void ACTION_free_package_structures( MSIPACKAGE* package)
{
......@@ -459,16 +469,11 @@ void ACTION_free_package_structures( MSIPACKAGE* 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 )
{
ComponentList *cl = LIST_ENTRY( item, ComponentList, entry );
list_remove( &cl->entry );
HeapFree(GetProcessHeap(), 0, cl);
}
HeapFree(GetProcessHeap(),0,package->features->Components);
HeapFree(GetProcessHeap(),0,package->features);
MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry );
list_remove( &feature->entry );
free_feature( feature );
}
for (i = 0; i < package->loaded_folders; i++)
......@@ -773,13 +778,12 @@ BOOL ACTION_VerifyComponentForAction(MSIPACKAGE* package, MSICOMPONENT* comp,
return FALSE;
}
BOOL ACTION_VerifyFeatureForAction(MSIPACKAGE* package, INT index,
INSTALLSTATE check )
BOOL ACTION_VerifyFeatureForAction( MSIFEATURE* feature, INSTALLSTATE check )
{
if (package->features[index].Installed == check)
if (feature->Installed == check)
return FALSE;
if (package->features[index].ActionRequest == check)
if (feature->ActionRequest == check)
return TRUE;
else
return FALSE;
......@@ -852,19 +856,17 @@ LPWSTR create_component_advertise_string(MSIPACKAGE* package,
/* update compoennt state based on a feature change */
void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
{
int i;
INSTALLSTATE newstate;
MSIFEATURE *feature;
ComponentList *cl;
i = get_loaded_feature(package,szFeature);
if (i < 0)
feature = get_loaded_feature(package,szFeature);
if (!feature)
return;
feature = &package->features[i];
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;
......@@ -883,27 +885,25 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
}
else
{
int j;
ComponentList *clist;
MSIFEATURE *f;
component->ActionRequest = newstate;
component->Action = newstate;
/*if any other feature wants is local we need to set it local*/
for (j = 0;
j < package->loaded_features &&
component->ActionRequest != INSTALLSTATE_LOCAL;
j++)
LIST_FOR_EACH_ENTRY( f, &package->features, MSIFEATURE, entry )
{
LIST_FOR_EACH_ENTRY( clist, package->features[j].Components,
ComponentList, entry )
if ( component->ActionRequest != INSTALLSTATE_LOCAL )
break;
LIST_FOR_EACH_ENTRY( clist, &f->Components, ComponentList, entry )
{
if ( clist->component == cl->component )
if ( clist->component == component )
{
if (package->features[j].ActionRequest ==
INSTALLSTATE_LOCAL)
if (f->ActionRequest == 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->Action = INSTALLSTATE_LOCAL;
}
......
......@@ -416,30 +416,29 @@ UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
INSTALLSTATE iState)
{
INT index, i;
UINT rc = ERROR_SUCCESS;
MSIFEATURE *feature, *child;
TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
index = get_loaded_feature(package,szFeature);
if (index < 0)
feature = get_loaded_feature(package,szFeature);
if (!feature)
return ERROR_UNKNOWN_FEATURE;
if (iState == INSTALLSTATE_ADVERTISED &&
package->features[index].Attributes &
msidbFeatureAttributesDisallowAdvertise)
feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
return ERROR_FUNCTION_FAILED;
package->features[index].ActionRequest= iState;
package->features[index].Action= iState;
feature->ActionRequest = iState;
feature->Action = iState;
ACTION_UpdateComponentStates(package,szFeature);
/* 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)
MSI_SetFeatureStateW(package, package->features[i].Feature, iState);
if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
MSI_SetFeatureStateW(package, child->Feature, iState);
}
return rc;
......@@ -487,19 +486,19 @@ UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPSTR szFeature,
UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature,
INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{
INT index;
MSIFEATURE *feature;
index = get_loaded_feature(package,szFeature);
if (index < 0)
feature = get_loaded_feature(package,szFeature);
if (!feature)
return ERROR_UNKNOWN_FEATURE;
if (piInstalled)
*piInstalled = package->features[index].Installed;
*piInstalled = feature->Installed;
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;
}
......@@ -547,8 +546,8 @@ UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPWSTR szComponent,
{
MSICOMPONENT *comp;
TRACE("%p %s %p %p\n", package, debugstr_w(szComponent), piInstalled,
piAction);
TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
piInstalled, piAction);
comp = get_loaded_component(package,szComponent);
if (!comp)
......@@ -560,8 +559,7 @@ piAction);
if (piAction)
*piAction = comp->Action;
TRACE("states (%i, %i)\n",
(piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1);
TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
return ERROR_SUCCESS;
}
......
......@@ -186,11 +186,10 @@ typedef struct tagMSIPACKAGE
{
MSIOBJECTHDR hdr;
MSIDATABASE *db;
struct tagMSIFEATURE *features;
UINT loaded_features;
struct tagMSIFOLDER *folders;
UINT loaded_folders;
struct list components;
struct list features;
struct tagMSIFILE *files;
UINT loaded_files;
LPWSTR ActionFormat;
......
......@@ -377,11 +377,10 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db )
msiobj_addref( &db->hdr );
package->db = db;
package->features = NULL;
list_init( &package->features );
package->folders = NULL;
list_init( &package->components );
package->files = NULL;
package->loaded_features = 0;
package->loaded_folders = 0;
package->loaded_files = 0;
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