msi: update installed state and such
Aric Stewart
aric at codeweavers.com
Mon Feb 21 17:18:47 CST 2005
update the installed state for components during CostFinalize. Laying
groundwork to be able to start processing uninstall logic as well.
-------------- next part --------------
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.88
diff -u -u -r1.88 action.c
--- dlls/msi/action.c 18 Feb 2005 20:00:34 -0000 1.88
+++ dlls/msi/action.c 21 Feb 2005 23:16:50 -0000
@@ -107,6 +107,8 @@
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 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};
@@ -802,6 +804,18 @@
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
@@ -1534,7 +1548,7 @@
sz = 96;
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].ActionRequest = INSTALLSTATE_UNKNOWN;
@@ -1599,7 +1613,7 @@
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].ActionRequest = INSTALLSTATE_UNKNOWN;
@@ -2069,6 +2083,46 @@
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 */
void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
{
@@ -2120,49 +2174,24 @@
}
}
-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 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};
-
- /* 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;
+ LPWSTR override = NULL;
+ INT i;
+ BOOL rc = FALSE;
- /* 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)
{
+ rc = TRUE;
for(i = 0; i < package->loaded_features; i++)
{
if (strcmpiW(override,all)==0)
{
- package->features[i].ActionRequest= INSTALLSTATE_LOCAL;
- package->features[i].Action = INSTALLSTATE_LOCAL;
+ package->features[i].ActionRequest= state;
+ package->features[i].Action = state;
}
else
{
@@ -2176,8 +2205,8 @@
|| (!ptr2 &&
strcmpW(ptr,package->features[i].Feature)==0))
{
- package->features[i].ActionRequest= INSTALLSTATE_LOCAL;
- package->features[i].Action = INSTALLSTATE_LOCAL;
+ package->features[i].ActionRequest= state;
+ package->features[i].Action = state;
break;
}
if (ptr2)
@@ -2192,16 +2221,72 @@
}
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
+ 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++)
{
- BOOL feature_state= ((package->features[i].Level > 0) &&
+ BOOL feature_state = ((package->features[i].Level > 0) &&
(package->features[i].Level <= install_level));
if (feature_state)
{
- package->features[i].ActionRequest= INSTALLSTATE_LOCAL;
+ package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
package->features[i].Action = INSTALLSTATE_LOCAL;
}
}
@@ -2225,15 +2310,24 @@
if (!component->Enabled)
{
- component->Action = INSTALLSTATE_ABSENT;
- component->ActionRequest = INSTALLSTATE_ABSENT;
+ component->Action = INSTALLSTATE_UNKNOWN;
+ component->ActionRequest = INSTALLSTATE_UNKNOWN;
}
else
{
if (feature->Action == INSTALLSTATE_LOCAL)
+ {
component->Action = INSTALLSTATE_LOCAL;
- if (feature->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 @@
else
HeapFree(GetProcessHeap(),0,level);
- return SetFeatureStates(package);
+ ACTION_UpdateInstallStates(package);
+ return SetFeatureStates(package);
}
/*
@@ -2867,8 +2962,9 @@
if (file->Temporary)
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);
TRACE("File %s is not scheduled for install\n",
@@ -3038,8 +3134,9 @@
}
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");
@@ -3280,8 +3377,8 @@
component = load_dynamic_stringW(row, 6);
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 write due to disabled component\n");
msiobj_release(&row->hdr);
@@ -3609,8 +3706,6 @@
UINT rc;
DWORD i;
HKEY hkey=0,hkey2=0;
- static const WCHAR szProductCode[]=
- {'P','r','o','d','u','c','t','C','o','d','e',0};
if (!package)
return ERROR_INVALID_HANDLE;
@@ -3719,7 +3814,8 @@
continue;
}
- if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)
+ if (!ACTION_VerifyComponentForAction(package, index,
+ INSTALLSTATE_LOCAL))
{
TRACE("Skipping typelib reg due to disabled component\n");
msiobj_release(&row->hdr);
@@ -3973,7 +4069,8 @@
continue;
}
- if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)
+ if (!ACTION_VerifyComponentForAction(package, index,
+ INSTALLSTATE_LOCAL))
{
TRACE("Skipping class reg due to disabled component\n");
msiobj_release(&row->hdr);
@@ -4392,8 +4489,6 @@
static const WCHAR szInstaller[] =
{'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[] =
{'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
@@ -4475,7 +4570,8 @@
continue;
}
- if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)
+ if (!ACTION_VerifyComponentForAction(package, index,
+ INSTALLSTATE_LOCAL))
{
TRACE("Skipping shortcut creation due to disabled component\n");
msiobj_release(&row->hdr);
@@ -4630,8 +4726,6 @@
LPWSTR productcode;
HKEY hkey=0;
HKEY hukey=0;
- static const WCHAR szProductCode[]=
- {'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szProductName[] = {
'P','r','o','d','u','c','t','N','a','m','e',0};
static const WCHAR szPackageCode[] = {
@@ -4824,8 +4918,8 @@
component_index = get_loaded_component(package,component);
HeapFree(GetProcessHeap(),0,component);
- if (package->components[component_index].ActionRequest !=
- INSTALLSTATE_LOCAL)
+ if (!ACTION_VerifyComponentForAction(package, component_index,
+ INSTALLSTATE_LOCAL))
{
TRACE("Skipping ini file due to disabled component\n");
msiobj_release(&row->hdr);
@@ -5008,8 +5102,6 @@
DWORD i;
HKEY hkey=0;
HKEY hukey=0;
- static const WCHAR szProductCode[]=
- {'P','r','o','d','u','c','t','C','o','d','e',0};
if (!package)
return ERROR_INVALID_HANDLE;
@@ -5081,8 +5173,6 @@
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;
LPWSTR buffer;
LPWSTR productcode;
@@ -5285,8 +5375,6 @@
WCHAR squished_pc[100];
INT rc;
DWORD size;
- static const WCHAR szProductCode[]=
- {'P','r','o','d','u','c','t','C','o','d','e',0};
static const WCHAR szLUS[] = {
'L','a','s','t','U','s','e','d','S','o','u','r','c','e',0};
static const WCHAR szSourceList[] = {
@@ -5409,7 +5497,8 @@
continue;
}
- if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL)
+ if (!ACTION_VerifyComponentForAction(package, index,
+ INSTALLSTATE_LOCAL))
{
TRACE("Skipping extension reg due to disabled component\n");
msiobj_release(&row->hdr);
@@ -5562,8 +5651,6 @@
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[]=
{'P','r','o','d','u','c','t','I','D',0};
HKEY hkey=0;
More information about the wine-patches
mailing list