MSI: really basic scripting

Aric Stewart aric at codeweavers.com
Fri May 27 10:35:47 CDT 2005


This Patch introduces really basic scripting of actions. This is 
primarily to get the order of execution of the action correct since some 
custom actions can be scripted and others are run during the script 
building phase.
-------------- next part --------------
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.124
diff -u -r1.124 action.c
--- dlls/msi/action.c	27 May 2005 09:11:18 -0000	1.124
+++ dlls/msi/action.c	27 May 2005 15:33:12 -0000
@@ -676,13 +676,18 @@
     if (package->appids && package->loaded_appids > 0)
         HeapFree(GetProcessHeap(),0,package->appids);
 
-    for (i = 0; i < package->DeferredActionCount; i++)
-        HeapFree(GetProcessHeap(),0,package->DeferredAction[i]);
-    HeapFree(GetProcessHeap(),0,package->DeferredAction);
-
-    for (i = 0; i < package->CommitActionCount; i++)
-        HeapFree(GetProcessHeap(),0,package->CommitAction[i]);
-    HeapFree(GetProcessHeap(),0,package->CommitAction);
+    if (package->script)
+    {
+        for (i = 0; i < TOTAL_SCRIPTS; i++)
+        {
+            int j;
+            for (j = 0; j < package->script->ActionCount[i]; j++)
+                HeapFree(GetProcessHeap(),0,package->script->Actions[i][j]);
+        
+            HeapFree(GetProcessHeap(),0,package->script->Actions[i]);
+        }
+        HeapFree(GetProcessHeap(),0,package->script);
+    }
 
     HeapFree(GetProcessHeap(),0,package->PackagePath);
 
@@ -963,7 +968,9 @@
     static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
 
     MSI_SetPropertyW(package, szAction, szInstall);
-    package->ExecuteSequenceRun = FALSE;
+
+    package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT));
+    memset(package->script,0,sizeof(MSISCRIPT));
 
     if (szPackagePath)   
     {
@@ -1073,15 +1080,17 @@
         rc = ERROR_SUCCESS;
     }
 
+    package->script->CurrentlyScripting= FALSE;
+
     /* process the ending type action */
     if (rc == ERROR_SUCCESS)
         ACTION_PerformActionSequence(package,-1,ui);
     else if (rc == ERROR_INSTALL_USEREXIT) 
         ACTION_PerformActionSequence(package,-2,ui);
-    else if (rc == ERROR_FUNCTION_FAILED) 
-        ACTION_PerformActionSequence(package,-3,ui);
     else if (rc == ERROR_INSTALL_SUSPEND) 
         ACTION_PerformActionSequence(package,-4,ui);
+    else  /* failed */
+        ACTION_PerformActionSequence(package,-3,ui);
 
     /* finish up running custom actions */
     ACTION_FinishCustomActions(package);
@@ -1165,7 +1174,7 @@
         if (UI)
             rc = ACTION_PerformUIAction(package,buffer);
         else
-            rc = ACTION_PerformAction(package,buffer);
+            rc = ACTION_PerformAction(package,buffer, FALSE);
         msiobj_release(&row->hdr);
 end:
         MSI_ViewClose(view);
@@ -1199,13 +1208,13 @@
     INT seq = 0;
 
 
-    if (package->ExecuteSequenceRun)
+    if (package->script->ExecuteSequenceRun)
     {
         TRACE("Execute Sequence already Run\n");
         return ERROR_SUCCESS;
     }
 
-    package->ExecuteSequenceRun = TRUE;
+    package->script->ExecuteSequenceRun = TRUE;
     
     /* get the sequence number */
     if (UIran)
@@ -1289,7 +1298,7 @@
                 break;
             }
 
-            rc = ACTION_PerformAction(package,buffer);
+            rc = ACTION_PerformAction(package,buffer, FALSE);
 
             if (rc == ERROR_FUNCTION_NOT_CALLED)
                 rc = ERROR_SUCCESS;
@@ -1413,29 +1422,49 @@
 /********************************************************
  * ACTION helper functions and functions that perform the actions
  *******************************************************/
-BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc)
+static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, 
+                                        UINT* rc, BOOL force )
 {
     BOOL ret = FALSE; 
-
+    BOOL run = force;
     int i;
+
+    if (!run && !package->script->CurrentlyScripting)
+        run = TRUE;
+   
+    if (!run)
+    {
+        if (strcmpW(action,szInstallFinalize) == 0 ||
+            strcmpW(action,szInstallExecute) == 0 ||
+            strcmpW(action,szInstallExecuteAgain) == 0) 
+                run = TRUE;
+    }
+    
     i = 0;
     while (StandardActions[i].action != NULL)
     {
         if (strcmpW(StandardActions[i].action, action)==0)
         {
             ce_actiontext(package, action);
-            ui_actioninfo(package, action, TRUE, 0);
-            ui_actionstart(package, action);
-            if (StandardActions[i].handler)
+            if (!run)
             {
-                *rc = StandardActions[i].handler(package);
+                ui_actioninfo(package, action, TRUE, 0);
+                *rc = schedule_action(package,INSTALL_SCRIPT,action);
+                ui_actioninfo(package, action, FALSE, *rc);
             }
             else
             {
-                FIXME("UNHANDLED Standard Action %s\n",debugstr_w(action));
-                *rc = ERROR_SUCCESS;
+                ui_actionstart(package, action);
+                if (StandardActions[i].handler)
+                {
+                    *rc = StandardActions[i].handler(package);
+                }
+                else
+                {
+                    FIXME("UNHANDLED Standard Action %s\n",debugstr_w(action));
+                    *rc = ERROR_SUCCESS;
+                }
             }
-            ui_actioninfo(package, action, FALSE, *rc);
             ret = TRUE;
             break;
         }
@@ -1456,12 +1485,13 @@
     return ret;
 }
 
-BOOL ACTION_HandleCustomAction(MSIPACKAGE* package, LPCWSTR action, UINT* rc)
+BOOL ACTION_HandleCustomAction(MSIPACKAGE* package, LPCWSTR action, UINT* rc, 
+                               BOOL force )
 {
     BOOL ret=FALSE;
     UINT arc;
 
-    arc = ACTION_CustomAction(package,action,FALSE);
+    arc = ACTION_CustomAction(package,action, force);
 
     if (arc != ERROR_CALL_NOT_IMPLEMENTED)
     {
@@ -1479,17 +1509,17 @@
  * But until I get write access to the database that is hard, so I am going to
  * hack it to see if I can get something to run.
  */
-UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
+UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force)
 {
     UINT rc = ERROR_SUCCESS; 
     BOOL handled;
 
     TRACE("Performing action (%s)\n",debugstr_w(action));
 
-    handled = ACTION_HandleStandardAction(package, action, &rc);
+    handled = ACTION_HandleStandardAction(package, action, &rc, force);
 
     if (!handled)
-        handled = ACTION_HandleCustomAction(package, action, &rc);
+        handled = ACTION_HandleCustomAction(package, action, &rc, force);
 
     if (!handled)
     {
@@ -1508,10 +1538,10 @@
 
     TRACE("Performing action (%s)\n",debugstr_w(action));
 
-    handled = ACTION_HandleStandardAction(package, action, &rc);
+    handled = ACTION_HandleStandardAction(package, action, &rc,TRUE);
 
     if (!handled)
-        handled = ACTION_HandleCustomAction(package, action, &rc);
+        handled = ACTION_HandleCustomAction(package, action, &rc, FALSE);
 
     if (!handled)
         handled = ACTION_HandleDialogBox(package, action, &rc);
@@ -2010,6 +2040,57 @@
     return ERROR_SUCCESS;
 }
 
+UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action)
+{
+    UINT count;
+    LPWSTR *newbuf = NULL;
+    if (script >= TOTAL_SCRIPTS)
+    {
+        FIXME("Unknown script requested %i\n",script);
+        return ERROR_FUNCTION_FAILED;
+    }
+    TRACE("Scheduling Action %s in script %i\n",debugstr_w(action), script);
+    
+    count = package->script->ActionCount[script];
+    package->script->ActionCount[script]++;
+    if (count != 0)
+        newbuf = HeapReAlloc(GetProcessHeap(),0,
+                        package->script->Actions[script],
+                        package->script->ActionCount[script]* sizeof(LPWSTR));
+    else
+        newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR));
+
+    newbuf[count] = strdupW(action);
+    package->script->Actions[script] = newbuf;
+
+   return ERROR_SUCCESS;
+}
+
+UINT execute_script(MSIPACKAGE *package, UINT script )
+{
+    int i;
+    UINT rc = ERROR_SUCCESS;
+
+    TRACE("Executing Script %i\n",script);
+
+    for (i = 0; i < package->script->ActionCount[script]; i++)
+    {
+        LPWSTR action;
+        action = package->script->Actions[script][i];
+        ui_actionstart(package, action);
+        TRACE("Executing Action (%s)\n",debugstr_w(action));
+        rc = ACTION_PerformAction(package, action, TRUE);
+        HeapFree(GetProcessHeap(),0,package->script->Actions[script][i]);
+        if (rc != ERROR_SUCCESS)
+            break;
+    }
+    HeapFree(GetProcessHeap(),0,package->script->Actions[script]);
+
+    package->script->ActionCount[script] = 0;
+    package->script->Actions[script] = NULL;
+    return rc;
+}
+
 static UINT ACTION_FileCost(MSIPACKAGE *package)
 {
     return ERROR_SUCCESS;
@@ -3829,6 +3910,8 @@
 
 static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
 {
+    package->script->CurrentlyScripting = TRUE;
+
     return ERROR_SUCCESS;
 }
 
@@ -6634,52 +6717,35 @@
 
 static UINT ACTION_InstallExecute(MSIPACKAGE *package)
 {
-    int i;
+    UINT rc;
+
     if (!package)
         return ERROR_INVALID_HANDLE;
 
-    for (i = 0; i < package->DeferredActionCount; i++)
-    {
-        LPWSTR action;
-        action = package->DeferredAction[i];
-        ui_actionstart(package, action);
-        TRACE("Executing Action (%s)\n",debugstr_w(action));
-        ACTION_CustomAction(package,action,TRUE);
-        HeapFree(GetProcessHeap(),0,package->DeferredAction[i]);
-    }
-    HeapFree(GetProcessHeap(),0,package->DeferredAction);
-
-    package->DeferredActionCount = 0;
-    package->DeferredAction = NULL;
+    rc = execute_script(package,INSTALL_SCRIPT);
 
-    return ERROR_SUCCESS;
+    return rc;
 }
 
 static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
 {
-    int i;
+    UINT rc;
+
     if (!package)
         return ERROR_INVALID_HANDLE;
 
+    /* turn off scheduleing */
+    package->script->CurrentlyScripting= FALSE;
+
     /* first do the same as an InstallExecute */
-    ACTION_InstallExecute(package);
+    rc = ACTION_InstallExecute(package);
+    if (rc != ERROR_SUCCESS)
+        return rc;
 
     /* then handle Commit Actions */
-    for (i = 0; i < package->CommitActionCount; i++)
-    {
-        LPWSTR action;
-        action = package->CommitAction[i];
-        ui_actionstart(package, action);
-        TRACE("Executing Commit Action (%s)\n",debugstr_w(action));
-        ACTION_CustomAction(package,action,TRUE);
-        HeapFree(GetProcessHeap(),0,package->CommitAction[i]);
-    }
-    HeapFree(GetProcessHeap(),0,package->CommitAction);
-
-    package->CommitActionCount = 0;
-    package->CommitAction = NULL;
+    rc = execute_script(package,COMMIT_SCRIPT);
 
-    return ERROR_SUCCESS;
+    return rc;
 }
 
 static UINT ACTION_ForceReboot(MSIPACKAGE *package)
Index: dlls/msi/action.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.h,v
retrieving revision 1.10
diff -u -r1.10 action.h
--- dlls/msi/action.h	27 May 2005 09:11:18 -0000	1.10
+++ dlls/msi/action.h	27 May 2005 15:33:12 -0000
@@ -179,8 +179,23 @@
     BOOL RunAsInteractiveUser;
 } MSIAPPID;
 
+enum SCRIPTS {
+        INSTALL_SCRIPT = 0,
+        COMMIT_SCRIPT = 1,
+        ROLLBACK_SCRIPT = 2,
+        TOTAL_SCRIPTS = 3
+};
 
-UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action);
+typedef struct tagMSISCRIPT
+{
+    LPWSTR  *Actions[TOTAL_SCRIPTS];
+    UINT    ActionCount[TOTAL_SCRIPTS];
+    BOOL    ExecuteSequenceRun;
+    BOOL    CurrentlyScripting;
+}MSISCRIPT;
+
+
+UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, BOOL force);
 UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action);
 void ACTION_FinishCustomActions( MSIPACKAGE* package);
 UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute);
@@ -196,6 +211,7 @@
 int 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);
 
 /* control event stuff */
 VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
Index: dlls/msi/custom.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/custom.c,v
retrieving revision 1.13
diff -u -r1.13 custom.c
--- dlls/msi/custom.c	20 May 2005 09:40:02 -0000	1.13
+++ dlls/msi/custom.c	27 May 2005 15:33:13 -0000
@@ -123,6 +123,7 @@
         if (type & 0x100)
         {
             FIXME("Rollback only action... rollbacks not supported yet\n");
+            schedule_action(package, ROLLBACK_SCRIPT, action);
             HeapFree(GetProcessHeap(),0,source);
             HeapFree(GetProcessHeap(),0,target);
             msiobj_release(&row->hdr);
@@ -132,37 +133,15 @@
         }
         if (!execute)
         {
-            LPWSTR *newbuf = NULL;
-            INT count;
             if (type & 0x200)
             {
                 TRACE("Deferring Commit Action!\n");
-                count = package->CommitActionCount;
-                package->CommitActionCount++;
-                if (count != 0)
-                    newbuf = HeapReAlloc(GetProcessHeap(),0,
-                        package->CommitAction,
-                        package->CommitActionCount * sizeof(LPWSTR));
-                else
-                    newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR));
-
-                newbuf[count] = strdupW(action);
-                package->CommitAction = newbuf;
+                schedule_action(package, COMMIT_SCRIPT, action);
             }
             else
             {
                 TRACE("Deferring Action!\n");
-                count = package->DeferredActionCount;
-                package->DeferredActionCount++;
-                if (count != 0)
-                    newbuf = HeapReAlloc(GetProcessHeap(),0,
-                        package->DeferredAction,
-                        package->DeferredActionCount * sizeof(LPWSTR));
-                else
-                    newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR));
-
-                newbuf[count] = strdupW(action);
-                package->DeferredAction = newbuf;
+                schedule_action(package, INSTALL_SCRIPT, action);
             }
 
             HeapFree(GetProcessHeap(),0,source);
Index: dlls/msi/events.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/events.c,v
retrieving revision 1.1
diff -u -r1.1 events.c
--- dlls/msi/events.c	27 May 2005 09:11:18 -0000	1.1
+++ dlls/msi/events.c	27 May 2005 15:33:13 -0000
@@ -163,7 +163,7 @@
 static VOID ControlEvent_DoAction(MSIPACKAGE* package, LPCWSTR argument, 
                                   msi_dialog* dialog)
 {
-    ACTION_PerformAction(package,argument);
+    ACTION_PerformAction(package,argument,TRUE);
 }
 
 static VOID ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument, 
Index: dlls/msi/msipriv.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/msipriv.h,v
retrieving revision 1.59
diff -u -r1.59 msipriv.h
--- dlls/msi/msipriv.h	27 May 2005 09:11:18 -0000	1.59
+++ dlls/msi/msipriv.h	27 May 2005 15:33:13 -0000
@@ -210,11 +210,7 @@
     struct tagMSIAPPID *appids;
     UINT loaded_appids;
     
-    LPWSTR *DeferredAction;
-    UINT DeferredActionCount;
-
-    LPWSTR *CommitAction;
-    UINT CommitActionCount;
+    struct tagMSISCRIPT *script;
 
     struct tagMSIRUNNINGACTION *RunningAction;
     UINT RunningActionCount;
@@ -224,8 +220,7 @@
     UINT CurrentInstallState;
     msi_dialog *dialog;
     LPWSTR next_dialog;
-
-    BOOL ExecuteSequenceRun;
+    
     struct _subscriptions *EventSubscriptions;
 } MSIPACKAGE;
 


More information about the wine-patches mailing list