msi: ExecuteAction change and improved Feature states

Aric Stewart aric at codeweavers.com
Thu May 12 14:33:43 CDT 2005


2 changes.

1) ExecuteAction runs the whole Execute table and not just from InstallValidate onward.  To do this make sure we do not do the costing initialization work again if it is already done (by checking the CostingComplete Property)
	
2) Alot of work to refine feature states, setting the state affects the state of all child features and also respect features that want to default to something other than LOCAL.

-------------- next part --------------
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.112
diff -u -r1.112 action.c
--- dlls/msi/action.c	9 May 2005 19:33:50 -0000	1.112
+++ dlls/msi/action.c	12 May 2005 19:27:57 -0000
@@ -1779,7 +1779,13 @@
     static const WCHAR szCosting[] =
         {'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 };
     static const WCHAR szZero[] = { '0', 0 };
+    WCHAR buffer[3];
+    DWORD sz = 3;
 
+    MSI_GetPropertyW(package, szCosting, buffer, &sz);
+    if (buffer[0]=='1')
+        return ERROR_SUCCESS;
+    
     MSI_SetPropertyW(package, szCosting, szZero);
     MSI_SetPropertyW(package, cszRootDrive , c_colon);
 
@@ -2205,17 +2211,25 @@
     {
         MSICOMPONENT* component = &package->components[feature->Components[i]];
 
+        TRACE("MODIFYING(%i): Component %s (Installed %i, Action %i, Request %i)\n",
+            newstate, debugstr_w(component->Component), component->Installed, 
+            component->Action, component->ActionRequest);
+        
         if (!component->Enabled)
             continue;
         else
         {
             if (newstate == INSTALLSTATE_LOCAL)
+            {
                 component->ActionRequest = INSTALLSTATE_LOCAL;
+                component->Action = INSTALLSTATE_LOCAL;
+            }
             else 
             {
                 int j,k;
 
                 component->ActionRequest = newstate;
+                component->Action = newstate;
 
                 /*if any other feature wants is local we need to set it local*/
                 for (j = 0; 
@@ -2229,12 +2243,19 @@
                         {
                             if (package->features[j].ActionRequest == 
                                 INSTALLSTATE_LOCAL)
+                            {
+                                TRACE("Saved by %s\n", debugstr_w(package->features[j].Feature));
                                 component->ActionRequest = INSTALLSTATE_LOCAL;
+                                component->Action = INSTALLSTATE_LOCAL;
+                            }
                             break;
                         }
                 }
             }
         }
+        TRACE("Result (%i): Component %s (Installed %i, Action %i, Request %i)\n",
+            newstate, debugstr_w(component->Component), component->Installed, 
+            component->Action, component->ActionRequest);
     } 
 }
 
@@ -2348,10 +2369,26 @@
             BOOL feature_state = ((package->features[i].Level > 0) &&
                              (package->features[i].Level <= install_level));
 
-            if (feature_state)
+            if ((feature_state) && 
+               (package->features[i].Action == INSTALLSTATE_UNKNOWN))
             {
-                package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
-                package->features[i].Action = INSTALLSTATE_LOCAL;
+                if (package->features[i].Attributes & 
+                                msidbFeatureAttributesFavorSource)
+                {
+                    package->features[i].ActionRequest = INSTALLSTATE_SOURCE;
+                    package->features[i].Action = INSTALLSTATE_SOURCE;
+                }
+                else if (package->features[i].Attributes &
+                                msidbFeatureAttributesFavorAdvertise)
+                {
+                    package->features[i].ActionRequest =INSTALLSTATE_ADVERTISED;
+                    package->features[i].Action =INSTALLSTATE_ADVERTISED;
+                }
+                else
+                {
+                    package->features[i].ActionRequest = INSTALLSTATE_LOCAL;
+                    package->features[i].Action = INSTALLSTATE_LOCAL;
+                }
             }
         }
     }
@@ -2384,6 +2421,27 @@
                     component->Action = INSTALLSTATE_LOCAL;
                     component->ActionRequest = INSTALLSTATE_LOCAL;
                 }
+                else if (feature->ActionRequest == INSTALLSTATE_SOURCE)
+                {
+                    if ((component->Action == INSTALLSTATE_UNKNOWN) ||
+                        (component->Action == INSTALLSTATE_ABSENT) ||
+                        (component->Action == INSTALLSTATE_ADVERTISED))
+                           
+                    {
+                        component->Action = INSTALLSTATE_SOURCE;
+                        component->ActionRequest = INSTALLSTATE_SOURCE;
+                    }
+                }
+                else if (feature->ActionRequest == INSTALLSTATE_ADVERTISED)
+                {
+                    if ((component->Action == INSTALLSTATE_UNKNOWN) ||
+                        (component->Action == INSTALLSTATE_ABSENT))
+                           
+                    {
+                        component->Action = INSTALLSTATE_ADVERTISED;
+                        component->ActionRequest = INSTALLSTATE_ADVERTISED;
+                    }
+                }
                 else if (feature->ActionRequest == INSTALLSTATE_ABSENT)
                 {
                     if (component->Action == INSTALLSTATE_UNKNOWN)
@@ -2432,6 +2490,12 @@
     MSIQUERY * view;
     DWORD i;
     LPWSTR level;
+    DWORD sz = 3;
+    WCHAR buffer[3];
+
+    MSI_GetPropertyW(package, szCosting, buffer, &sz);
+    if (buffer[0]=='1')
+        return ERROR_SUCCESS;
 
     TRACE("Building Directory properties\n");
 
@@ -3633,6 +3697,14 @@
         total += package->files[i].FileSize;
     ui_progress(package,0,total,0,0);
 
+    for(i = 0; i < package->loaded_features; i++)
+    {
+        MSIFEATURE* feature = &package->features[i];
+        TRACE("Feature: %s; Installed: %i; Action %i; Request %i\n",
+            debugstr_w(feature->Feature), feature->Installed, feature->Action,
+            feature->ActionRequest);
+    }
+    
     return ERROR_SUCCESS;
 }
 
@@ -3945,9 +4017,6 @@
             MSIRECORD * uirow;
 
             squash_guid(package->components[i].ComponentId,squished_cc);
-            rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
-            if (rc != ERROR_SUCCESS)
-                continue;
            
             keypath = resolve_keypath(package,i);
             package->components[i].FullKeypath = keypath;
@@ -3966,6 +4035,10 @@
             if (ACTION_VerifyComponentForAction(package, i,
                                     INSTALLSTATE_LOCAL))
             {
+                rc = RegCreateKeyW(hkey,squished_cc,&hkey2);
+                if (rc != ERROR_SUCCESS)
+                    continue;
+
                 if (keypath)
                 {
                     RegSetValueExW(hkey2,squished_pc,0,REG_SZ,(LPVOID)keypath,
@@ -4000,6 +4073,11 @@
                                     INSTALLSTATE_ABSENT))
             {
                 DWORD res;
+
+                rc = RegOpenKeyW(hkey,squished_cc,&hkey2);
+                if (rc != ERROR_SUCCESS)
+                    continue;
+
                 RegDeleteValueW(hkey2,squished_pc);
 
                 /* if the key is empty delete it */
@@ -5464,9 +5542,12 @@
         GUID clsid;
         int j;
         INT size;
+        BOOL absent = FALSE;
 
-        if (!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_LOCAL))
-            continue;
+        if (!ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_LOCAL) &&
+            !ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_SOURCE) &&
+            !ACTION_VerifyFeatureForAction(package,i,INSTALLSTATE_ADVERTISED))
+            absent = TRUE;
 
         size = package->features[i].ComponentCount*21;
         size +=1;
@@ -5501,9 +5582,23 @@
                        (LPSTR)data,size);
         HeapFree(GetProcessHeap(),0,data);
 
-        size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
-        RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
+        if (!absent)
+        {
+            size = strlenW(package->features[i].Feature_Parent)*sizeof(WCHAR);
+            RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
                        (LPSTR)package->features[i].Feature_Parent,size);
+        }
+        else
+        {
+            size = (strlenW(package->features[i].Feature_Parent)+2)*
+                    sizeof(WCHAR);
+            data = HeapAlloc(GetProcessHeap(),0,size);
+            data[0] = 0x6;
+            strcpyW(&data[1],package->features[i].Feature_Parent);
+            RegSetValueExW(hukey,package->features[i].Feature,0,REG_SZ,
+                       (LPSTR)data,size);
+            HeapFree(GetProcessHeap(),0,data);
+        }
     }
 
 end:
@@ -6061,7 +6156,7 @@
 static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
 {
     UINT rc;
-    rc = ACTION_ProcessExecSequence(package,TRUE);
+    rc = ACTION_ProcessExecSequence(package,FALSE);
     return rc;
 }
 
@@ -6321,6 +6416,23 @@
     static WCHAR fmt2[] = {'%','s','%','s','>','%','s',0,0};
     LPWSTR output = NULL;
     DWORD sz = 0;
+    INT component_index;
+
+    component = load_dynamic_stringW(rec,3);
+    component_index = get_loaded_component(package,component);
+
+    if (!ACTION_VerifyComponentForAction(package, component_index,
+                            INSTALLSTATE_LOCAL) && 
+       !ACTION_VerifyComponentForAction(package, component_index,
+                            INSTALLSTATE_SOURCE) &&
+       !ACTION_VerifyComponentForAction(package, component_index,
+                            INSTALLSTATE_ADVERTISED))
+    {
+        TRACE("Skipping: Component %s not scheduled for install\n",
+                        debugstr_w(component));
+        HeapFree(GetProcessHeap(),0,component);
+        return ERROR_SUCCESS;
+    }
 
     memset(productid_85,0,sizeof(productid_85));
     memset(component_85,0,sizeof(component_85));
@@ -6339,7 +6451,6 @@
     qualifier = load_dynamic_stringW(rec,2);
 
     feature = load_dynamic_stringW(rec,5);
-    component = load_dynamic_stringW(rec,3);
   
     index = get_loaded_component(package, component);
     CLSIDFromString(package->components[index].ComponentId, &clsid);
@@ -6756,6 +6867,35 @@
     return rc;
 }
 
+
+
+UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
+                                INSTALLSTATE iState)
+{
+    INT index, i;
+    UINT rc = ERROR_SUCCESS;
+
+    TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
+
+    index = get_loaded_feature(package,szFeature);
+    if (index < 0)
+        return ERROR_UNKNOWN_FEATURE;
+
+    package->features[index].ActionRequest= iState;
+    package->features[index].Action= iState;
+
+    ACTION_UpdateComponentStates(package,szFeature);
+
+    /* update all the features that are children of this feature */
+    for (i = 0; i < package->loaded_features; i++)
+    {
+        if (strcmpW(szFeature, package->features[i].Feature_Parent) == 0)
+            MSI_SetFeatureStateW(package, package->features[i].Feature, iState);
+    }
+    
+    return rc;
+}
+
 /***********************************************************************
  * MsiSetFeatureStateW (MSI.@)
  */
@@ -6763,7 +6903,6 @@
                                 INSTALLSTATE iState)
 {
     MSIPACKAGE* package;
-    INT index;
     UINT rc = ERROR_SUCCESS;
 
     TRACE(" %s to %i\n",debugstr_w(szFeature), iState);
@@ -6772,17 +6911,8 @@
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    index = get_loaded_feature(package,szFeature);
-    if (index < 0)
-    {
-        rc = ERROR_UNKNOWN_FEATURE;
-        goto end;
-    }
-
-    package->features[index].ActionRequest= iState;
-    ACTION_UpdateComponentStates(package,szFeature);
+    rc = MSI_SetFeatureStateW(package,szFeature,iState);
 
-end:
     msiobj_release( &package->hdr );
     return rc;
 }
Index: dlls/msi/msipriv.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/msipriv.h,v
retrieving revision 1.54
diff -u -r1.54 msipriv.h
--- dlls/msi/msipriv.h	27 Apr 2005 10:16:57 -0000	1.54
+++ dlls/msi/msipriv.h	12 May 2005 19:27:57 -0000
@@ -342,6 +342,7 @@
 extern UINT MSI_SetPropertyW( MSIPACKAGE *, LPCWSTR, LPCWSTR );
 extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE * );
 extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPWSTR, INSTALLSTATE *, INSTALLSTATE * );
+extern UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE*, LPCWSTR, INSTALLSTATE );
 
 /* for deformating */
 extern UINT MSI_FormatRecordW(MSIPACKAGE* package, MSIRECORD* record, 


More information about the wine-patches mailing list