Update the installed state for components during CostFinalize. Laying

groundwork to be able to start processing uninstall logic as well.
This commit is contained in:
Aric Stewart 2005-02-22 15:47:00 +00:00 committed by Alexandre Julliard
parent dfa4354134
commit 78a04e39db
1 changed files with 157 additions and 70 deletions

View File

@ -107,6 +107,8 @@ static const WCHAR cszTargetDir[] = {'T','A','R','G','E','T','D','I','R',0};
static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0}; static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0}; static const WCHAR cszDatabase[]={'D','A','T','A','B','A','S','E',0};
static const WCHAR c_collen[] = {'C',':','\\',0}; static const WCHAR c_collen[] = {'C',':','\\',0};
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR cszbs[]={'\\',0}; static const WCHAR cszbs[]={'\\',0};
@ -802,6 +804,18 @@ static LPWSTR build_directory_name(DWORD count, ...)
return dir; return dir;
} }
static BOOL ACTION_VerifyComponentForAction(MSIPACKAGE* package, INT index,
INSTALLSTATE check )
{
if (package->components[index].Installed == check)
return FALSE;
if (package->components[index].ActionRequest == check)
return TRUE;
else
return FALSE;
}
/**************************************************** /****************************************************
* TOP level entry points * TOP level entry points
@ -1534,7 +1548,7 @@ static int load_component(MSIPACKAGE* package, MSIRECORD * row)
sz = 96; sz = 96;
MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz); MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz);
package->components[index].Installed = INSTALLSTATE_ABSENT; package->components[index].Installed = INSTALLSTATE_UNKNOWN;
package->components[index].Action = INSTALLSTATE_UNKNOWN; package->components[index].Action = INSTALLSTATE_UNKNOWN;
package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN; package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN;
@ -1599,7 +1613,7 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row)
package->features[index].Attributes= MSI_RecordGetInteger(row,8); package->features[index].Attributes= MSI_RecordGetInteger(row,8);
package->features[index].Installed = INSTALLSTATE_ABSENT; package->features[index].Installed = INSTALLSTATE_UNKNOWN;
package->features[index].Action = INSTALLSTATE_UNKNOWN; package->features[index].Action = INSTALLSTATE_UNKNOWN;
package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN; package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN;
@ -2069,6 +2083,46 @@ LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source,
return path; return path;
} }
/* scan for and update current install states */
void ACTION_UpdateInstallStates(MSIPACKAGE *package)
{
int i;
LPWSTR productcode;
productcode = load_dynamic_property(package,szProductCode,NULL);
for (i = 0; i < package->loaded_components; i++)
{
INSTALLSTATE res;
res = MsiGetComponentPathW(productcode,
package->components[i].ComponentId , NULL, NULL);
if (res < 0)
res = INSTALLSTATE_ABSENT;
package->components[i].Installed = res;
}
for (i = 0; i < package->loaded_features; i++)
{
INSTALLSTATE res = -10;
int j;
for (j = 0; j < package->features[i].ComponentCount; j++)
{
MSICOMPONENT* component = &package->components[package->features[i].
Components[j]];
if (res == -10)
res = component->Installed;
else
{
if (res == component->Installed)
continue;
if (res != component->Installed)
res = INSTALLSTATE_INCOMPLETE;
}
}
}
}
/* 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)
{ {
@ -2120,49 +2174,24 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
} }
} }
static UINT SetFeatureStates(MSIPACKAGE *package) static BOOL process_state_property (MSIPACKAGE* package, LPCWSTR property,
INSTALLSTATE state)
{ {
LPWSTR level;
INT install_level;
DWORD i;
INT j;
LPWSTR override = NULL;
static const WCHAR all[]={'A','L','L',0}; static const WCHAR all[]={'A','L','L',0};
static const WCHAR szlevel[] = { LPWSTR override = NULL;
'I','N','S','T','A','L','L','L','E','V','E','L',0}; INT i;
static const WCHAR szAddLocal[] = { BOOL rc = FALSE;
'A','D','D','L','O','C','A','L',0};
/* I do not know if this is where it should happen.. but */
TRACE("Checking Install Level\n");
level = load_dynamic_property(package,szlevel,NULL);
if (level)
{
install_level = atoiW(level);
HeapFree(GetProcessHeap(), 0, level);
}
else
install_level = 1;
/* ok hereis the rub
* ADDLOCAL and its friend OVERRIDE INSTALLLEVLE
* I have confirmed this if ADDLOCALis stated then the INSTALLLEVEL is
* itnored for all the features. seems strange, epsecially since it is not
* documented anywhere, but it is how it works.
*/
override = load_dynamic_property(package,szAddLocal,NULL);
override = load_dynamic_property(package, property, NULL);
if (override) if (override)
{ {
rc = TRUE;
for(i = 0; i < package->loaded_features; i++) for(i = 0; i < package->loaded_features; i++)
{ {
if (strcmpiW(override,all)==0) if (strcmpiW(override,all)==0)
{ {
package->features[i].ActionRequest= INSTALLSTATE_LOCAL; package->features[i].ActionRequest= state;
package->features[i].Action = INSTALLSTATE_LOCAL; package->features[i].Action = state;
} }
else else
{ {
@ -2176,8 +2205,8 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
|| (!ptr2 && || (!ptr2 &&
strcmpW(ptr,package->features[i].Feature)==0)) strcmpW(ptr,package->features[i].Feature)==0))
{ {
package->features[i].ActionRequest= INSTALLSTATE_LOCAL; package->features[i].ActionRequest= state;
package->features[i].Action = INSTALLSTATE_LOCAL; package->features[i].Action = state;
break; break;
} }
if (ptr2) if (ptr2)
@ -2192,16 +2221,72 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
} }
HeapFree(GetProcessHeap(),0,override); HeapFree(GetProcessHeap(),0,override);
} }
return rc;
}
static UINT SetFeatureStates(MSIPACKAGE *package)
{
LPWSTR level;
INT install_level;
DWORD i;
INT j;
static const WCHAR szlevel[] = {
'I','N','S','T','A','L','L','L','E','V','E','L',0};
static const WCHAR szAddLocal[] = {
'A','D','D','L','O','C','A','L',0};
static const WCHAR szRemove[] = {
'R','E','M','O','V','E',0};
BOOL override = FALSE;
/* I do not know if this is where it should happen.. but */
TRACE("Checking Install Level\n");
level = load_dynamic_property(package,szlevel,NULL);
if (level)
{
install_level = atoiW(level);
HeapFree(GetProcessHeap(), 0, level);
}
else else
install_level = 1;
/* ok hereis the _real_ rub
* all these activation/deactiontion things happen in order and things later
* on the list override things earlier on the list.
* 1) INSTALLLEVEL processing
* 2) ADDLOCAL
* 3) REMOVE
* 4) ADDSOURCE
* 5) ADDDEFAULT
* 6) REINSTALL
* 7) COMPADDLOCAL
* 8) COMPADDSOURCE
* 9) FILEADDLOCAL
* 10) FILEADDSOURCE
* 11) FILEADDDEFAULT
* I have confirmed this if ADDLOCALis stated then the INSTALLLEVEL is
* itnored for all the features. seems strange, epsecially since it is not
* documented anywhere, but it is how it works.
*
* I am still ignoring alot of these. But that is ok for now, ADDLOCAL and
* REMOVE are the big ones, since we dont handle administrative installs yet
* anyway.
*/
override |= process_state_property(package,szAddLocal,INSTALLSTATE_LOCAL);
override |= process_state_property(package,szRemove,INSTALLSTATE_ABSENT);
if (!override)
{ {
for(i = 0; i < package->loaded_features; i++) for(i = 0; i < package->loaded_features; i++)
{ {
BOOL feature_state= ((package->features[i].Level > 0) && BOOL feature_state = ((package->features[i].Level > 0) &&
(package->features[i].Level <= install_level)); (package->features[i].Level <= install_level));
if (feature_state) if (feature_state)
{ {
package->features[i].ActionRequest= INSTALLSTATE_LOCAL; package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
package->features[i].Action = INSTALLSTATE_LOCAL; package->features[i].Action = INSTALLSTATE_LOCAL;
} }
} }
@ -2225,15 +2310,24 @@ static UINT SetFeatureStates(MSIPACKAGE *package)
if (!component->Enabled) if (!component->Enabled)
{ {
component->Action = INSTALLSTATE_ABSENT; component->Action = INSTALLSTATE_UNKNOWN;
component->ActionRequest = INSTALLSTATE_ABSENT; component->ActionRequest = INSTALLSTATE_UNKNOWN;
} }
else else
{ {
if (feature->Action == INSTALLSTATE_LOCAL) if (feature->Action == INSTALLSTATE_LOCAL)
{
component->Action = INSTALLSTATE_LOCAL; component->Action = INSTALLSTATE_LOCAL;
if (feature->ActionRequest == INSTALLSTATE_LOCAL)
component->ActionRequest = INSTALLSTATE_LOCAL; component->ActionRequest = INSTALLSTATE_LOCAL;
}
else if (feature->ActionRequest == INSTALLSTATE_ABSENT)
{
if (component->Action == INSTALLSTATE_UNKNOWN)
{
component->Action = INSTALLSTATE_ABSENT;
component->ActionRequest = INSTALLSTATE_ABSENT;
}
}
} }
} }
} }
@ -2481,8 +2575,9 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
else else
HeapFree(GetProcessHeap(),0,level); HeapFree(GetProcessHeap(),0,level);
return SetFeatureStates(package); ACTION_UpdateInstallStates(package);
return SetFeatureStates(package);
} }
/* /*
@ -2867,8 +2962,9 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package)
if (file->Temporary) if (file->Temporary)
continue; continue;
if (package->components[file->ComponentIndex].ActionRequest !=
INSTALLSTATE_LOCAL) if (!ACTION_VerifyComponentForAction(package, file->ComponentIndex,
INSTALLSTATE_LOCAL))
{ {
ui_progress(package,2,file->FileSize,0,0); ui_progress(package,2,file->FileSize,0,0);
TRACE("File %s is not scheduled for install\n", TRACE("File %s is not scheduled for install\n",
@ -3038,8 +3134,9 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
} }
component_index = get_loaded_component(package,component); component_index = get_loaded_component(package,component);
if (package->components[component_index].ActionRequest !=
INSTALLSTATE_LOCAL) if (!ACTION_VerifyComponentForAction(package, component_index,
INSTALLSTATE_LOCAL))
{ {
TRACE("Skipping copy due to disabled component\n"); TRACE("Skipping copy due to disabled component\n");
@ -3280,8 +3377,8 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
component = load_dynamic_stringW(row, 6); component = load_dynamic_stringW(row, 6);
component_index = get_loaded_component(package,component); component_index = get_loaded_component(package,component);
if (package->components[component_index].ActionRequest != if (!ACTION_VerifyComponentForAction(package, component_index,
INSTALLSTATE_LOCAL) INSTALLSTATE_LOCAL))
{ {
TRACE("Skipping write due to disabled component\n"); TRACE("Skipping write due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
@ -3609,8 +3706,6 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
UINT rc; UINT rc;
DWORD i; DWORD i;
HKEY hkey=0,hkey2=0; HKEY hkey=0,hkey2=0;
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
if (!package) if (!package)
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
@ -3719,7 +3814,8 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
continue; continue;
} }
if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) if (!ACTION_VerifyComponentForAction(package, index,
INSTALLSTATE_LOCAL))
{ {
TRACE("Skipping typelib reg due to disabled component\n"); TRACE("Skipping typelib reg due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
@ -3973,7 +4069,8 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
continue; continue;
} }
if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) if (!ACTION_VerifyComponentForAction(package, index,
INSTALLSTATE_LOCAL))
{ {
TRACE("Skipping class reg due to disabled component\n"); TRACE("Skipping class reg due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
@ -4392,8 +4489,6 @@ static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
static const WCHAR szInstaller[] = static const WCHAR szInstaller[] =
{'I','n','s','t','a','l','l','e','r','\\',0}; {'I','n','s','t','a','l','l','e','r','\\',0};
static const WCHAR szProductCode[] =
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szFolder[] = static const WCHAR szFolder[] =
{'W','i','n','d','o','w','s','F','o','l','d','e','r',0}; {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
@ -4475,7 +4570,8 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
continue; continue;
} }
if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) if (!ACTION_VerifyComponentForAction(package, index,
INSTALLSTATE_LOCAL))
{ {
TRACE("Skipping shortcut creation due to disabled component\n"); TRACE("Skipping shortcut creation due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
@ -4630,8 +4726,6 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
LPWSTR productcode; LPWSTR productcode;
HKEY hkey=0; HKEY hkey=0;
HKEY hukey=0; HKEY hukey=0;
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szProductName[] = { static const WCHAR szProductName[] = {
'P','r','o','d','u','c','t','N','a','m','e',0}; 'P','r','o','d','u','c','t','N','a','m','e',0};
static const WCHAR szPackageCode[] = { static const WCHAR szPackageCode[] = {
@ -4824,8 +4918,8 @@ static UINT ACTION_WriteIniValues(MSIPACKAGE *package)
component_index = get_loaded_component(package,component); component_index = get_loaded_component(package,component);
HeapFree(GetProcessHeap(),0,component); HeapFree(GetProcessHeap(),0,component);
if (package->components[component_index].ActionRequest != if (!ACTION_VerifyComponentForAction(package, component_index,
INSTALLSTATE_LOCAL) INSTALLSTATE_LOCAL))
{ {
TRACE("Skipping ini file due to disabled component\n"); TRACE("Skipping ini file due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
@ -5008,8 +5102,6 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package)
DWORD i; DWORD i;
HKEY hkey=0; HKEY hkey=0;
HKEY hukey=0; HKEY hukey=0;
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
if (!package) if (!package)
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
@ -5081,8 +5173,6 @@ end:
static UINT ACTION_RegisterProduct(MSIPACKAGE *package) static UINT ACTION_RegisterProduct(MSIPACKAGE *package)
{ {
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
HKEY hkey=0; HKEY hkey=0;
LPWSTR buffer; LPWSTR buffer;
LPWSTR productcode; LPWSTR productcode;
@ -5285,8 +5375,6 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package)
WCHAR squished_pc[100]; WCHAR squished_pc[100];
INT rc; INT rc;
DWORD size; DWORD size;
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szLUS[] = { static const WCHAR szLUS[] = {
'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0}; 'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
static const WCHAR szSourceList[] = { static const WCHAR szSourceList[] = {
@ -5409,7 +5497,8 @@ static UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
continue; continue;
} }
if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) if (!ACTION_VerifyComponentForAction(package, index,
INSTALLSTATE_LOCAL))
{ {
TRACE("Skipping extension reg due to disabled component\n"); TRACE("Skipping extension reg due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
@ -5562,8 +5651,6 @@ end:
static UINT ACTION_RegisterUser(MSIPACKAGE *package) static UINT ACTION_RegisterUser(MSIPACKAGE *package)
{ {
static const WCHAR szProductCode[]=
{'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szProductID[]= static const WCHAR szProductID[]=
{'P','r','o','d','u','c','t','I','D',0}; {'P','r','o','d','u','c','t','I','D',0};
HKEY hkey=0; HKEY hkey=0;