Introduce 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.
This commit is contained in:
Aric Stewart 2005-05-27 19:24:22 +00:00 committed by Alexandre Julliard
parent aa95731d6f
commit 9cd707da3f
5 changed files with 150 additions and 94 deletions

View File

@ -676,13 +676,18 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
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);
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]);
for (i = 0; i < package->CommitActionCount; i++)
HeapFree(GetProcessHeap(),0,package->CommitAction[i]);
HeapFree(GetProcessHeap(),0,package->CommitAction);
HeapFree(GetProcessHeap(),0,package->script->Actions[i]);
}
HeapFree(GetProcessHeap(),0,package->script);
}
HeapFree(GetProcessHeap(),0,package->PackagePath);
@ -963,7 +968,9 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
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 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
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 @@ static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI)
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 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
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 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
break;
}
rc = ACTION_PerformAction(package,buffer);
rc = ACTION_PerformAction(package,buffer, FALSE);
if (rc == ERROR_FUNCTION_NOT_CALLED)
rc = ERROR_SUCCESS;
@ -1413,18 +1422,38 @@ end:
/********************************************************
* 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);
if (!run)
{
ui_actioninfo(package, action, TRUE, 0);
*rc = schedule_action(package,INSTALL_SCRIPT,action);
ui_actioninfo(package, action, FALSE, *rc);
}
else
{
ui_actionstart(package, action);
if (StandardActions[i].handler)
{
@ -1435,7 +1464,7 @@ BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc)
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 @@ BOOL ACTION_HandleDialogBox(MSIPACKAGE *package, LPCWSTR dialog, UINT* rc)
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 @@ BOOL ACTION_HandleCustomAction(MSIPACKAGE* package, LPCWSTR action, UINT* rc)
* 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 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action)
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 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
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 @@ next:
static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
{
package->script->CurrentlyScripting = TRUE;
return ERROR_SUCCESS;
}
@ -6634,52 +6717,35 @@ end:
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);
rc = execute_script(package,INSTALL_SCRIPT);
package->DeferredActionCount = 0;
package->DeferredAction = NULL;
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);
rc = execute_script(package,COMMIT_SCRIPT);
package->CommitActionCount = 0;
package->CommitAction = NULL;
return ERROR_SUCCESS;
return rc;
}
static UINT ACTION_ForceReboot(MSIPACKAGE *package)

View File

@ -179,8 +179,23 @@ typedef struct tagMSIAPPID
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_component(MSIPACKAGE* package, LPCWSTR Component );
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,

View File

@ -123,6 +123,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
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 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
}
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);

View File

@ -163,7 +163,7 @@ static VOID ControlEvent_SpawnWaitDialog(MSIPACKAGE* package, LPCWSTR argument,
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,

View File

@ -210,11 +210,7 @@ typedef struct tagMSIPACKAGE
struct tagMSIAPPID *appids;
UINT loaded_appids;
LPWSTR *DeferredAction;
UINT DeferredActionCount;
LPWSTR *CommitAction;
UINT CommitActionCount;
struct tagMSISCRIPT *script;
struct tagMSIRUNNINGACTION *RunningAction;
UINT RunningActionCount;
@ -225,7 +221,6 @@ typedef struct tagMSIPACKAGE
msi_dialog *dialog;
LPWSTR next_dialog;
BOOL ExecuteSequenceRun;
struct _subscriptions *EventSubscriptions;
} MSIPACKAGE;