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) if (package->appids && package->loaded_appids > 0)
HeapFree(GetProcessHeap(),0,package->appids); HeapFree(GetProcessHeap(),0,package->appids);
for (i = 0; i < package->DeferredActionCount; i++) if (package->script)
HeapFree(GetProcessHeap(),0,package->DeferredAction[i]); {
HeapFree(GetProcessHeap(),0,package->DeferredAction); for (i = 0; i < TOTAL_SCRIPTS; i++)
{
for (i = 0; i < package->CommitActionCount; i++) int j;
HeapFree(GetProcessHeap(),0,package->CommitAction[i]); for (j = 0; j < package->script->ActionCount[i]; j++)
HeapFree(GetProcessHeap(),0,package->CommitAction); 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); 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}; static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
MSI_SetPropertyW(package, szAction, szInstall); MSI_SetPropertyW(package, szAction, szInstall);
package->ExecuteSequenceRun = FALSE;
package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT));
memset(package->script,0,sizeof(MSISCRIPT));
if (szPackagePath) if (szPackagePath)
{ {
@ -1073,15 +1080,17 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
rc = ERROR_SUCCESS; rc = ERROR_SUCCESS;
} }
package->script->CurrentlyScripting= FALSE;
/* process the ending type action */ /* process the ending type action */
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
ACTION_PerformActionSequence(package,-1,ui); ACTION_PerformActionSequence(package,-1,ui);
else if (rc == ERROR_INSTALL_USEREXIT) else if (rc == ERROR_INSTALL_USEREXIT)
ACTION_PerformActionSequence(package,-2,ui); ACTION_PerformActionSequence(package,-2,ui);
else if (rc == ERROR_FUNCTION_FAILED)
ACTION_PerformActionSequence(package,-3,ui);
else if (rc == ERROR_INSTALL_SUSPEND) else if (rc == ERROR_INSTALL_SUSPEND)
ACTION_PerformActionSequence(package,-4,ui); ACTION_PerformActionSequence(package,-4,ui);
else /* failed */
ACTION_PerformActionSequence(package,-3,ui);
/* finish up running custom actions */ /* finish up running custom actions */
ACTION_FinishCustomActions(package); ACTION_FinishCustomActions(package);
@ -1165,7 +1174,7 @@ static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI)
if (UI) if (UI)
rc = ACTION_PerformUIAction(package,buffer); rc = ACTION_PerformUIAction(package,buffer);
else else
rc = ACTION_PerformAction(package,buffer); rc = ACTION_PerformAction(package,buffer, FALSE);
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
end: end:
MSI_ViewClose(view); MSI_ViewClose(view);
@ -1199,13 +1208,13 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
INT seq = 0; INT seq = 0;
if (package->ExecuteSequenceRun) if (package->script->ExecuteSequenceRun)
{ {
TRACE("Execute Sequence already Run\n"); TRACE("Execute Sequence already Run\n");
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
package->ExecuteSequenceRun = TRUE; package->script->ExecuteSequenceRun = TRUE;
/* get the sequence number */ /* get the sequence number */
if (UIran) if (UIran)
@ -1289,7 +1298,7 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran)
break; break;
} }
rc = ACTION_PerformAction(package,buffer); rc = ACTION_PerformAction(package,buffer, FALSE);
if (rc == ERROR_FUNCTION_NOT_CALLED) if (rc == ERROR_FUNCTION_NOT_CALLED)
rc = ERROR_SUCCESS; rc = ERROR_SUCCESS;
@ -1413,29 +1422,49 @@ end:
/******************************************************** /********************************************************
* ACTION helper functions and functions that perform the actions * 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 ret = FALSE;
BOOL run = force;
int i; 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; i = 0;
while (StandardActions[i].action != NULL) while (StandardActions[i].action != NULL)
{ {
if (strcmpW(StandardActions[i].action, action)==0) if (strcmpW(StandardActions[i].action, action)==0)
{ {
ce_actiontext(package, action); ce_actiontext(package, action);
ui_actioninfo(package, action, TRUE, 0); if (!run)
ui_actionstart(package, action);
if (StandardActions[i].handler)
{ {
*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 else
{ {
FIXME("UNHANDLED Standard Action %s\n",debugstr_w(action)); ui_actionstart(package, action);
*rc = ERROR_SUCCESS; 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; ret = TRUE;
break; break;
} }
@ -1456,12 +1485,13 @@ BOOL ACTION_HandleDialogBox(MSIPACKAGE *package, LPCWSTR dialog, UINT* rc)
return ret; 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; BOOL ret=FALSE;
UINT arc; UINT arc;
arc = ACTION_CustomAction(package,action,FALSE); arc = ACTION_CustomAction(package,action, force);
if (arc != ERROR_CALL_NOT_IMPLEMENTED) 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 * 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. * 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; UINT rc = ERROR_SUCCESS;
BOOL handled; BOOL handled;
TRACE("Performing action (%s)\n",debugstr_w(action)); TRACE("Performing action (%s)\n",debugstr_w(action));
handled = ACTION_HandleStandardAction(package, action, &rc); handled = ACTION_HandleStandardAction(package, action, &rc, force);
if (!handled) if (!handled)
handled = ACTION_HandleCustomAction(package, action, &rc); handled = ACTION_HandleCustomAction(package, action, &rc, force);
if (!handled) if (!handled)
{ {
@ -1508,10 +1538,10 @@ UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action)
TRACE("Performing action (%s)\n",debugstr_w(action)); TRACE("Performing action (%s)\n",debugstr_w(action));
handled = ACTION_HandleStandardAction(package, action, &rc); handled = ACTION_HandleStandardAction(package, action, &rc,TRUE);
if (!handled) if (!handled)
handled = ACTION_HandleCustomAction(package, action, &rc); handled = ACTION_HandleCustomAction(package, action, &rc, FALSE);
if (!handled) if (!handled)
handled = ACTION_HandleDialogBox(package, action, &rc); handled = ACTION_HandleDialogBox(package, action, &rc);
@ -2010,6 +2040,57 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
return ERROR_SUCCESS; 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) static UINT ACTION_FileCost(MSIPACKAGE *package)
{ {
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -3829,6 +3910,8 @@ next:
static UINT ACTION_InstallInitialize(MSIPACKAGE *package) static UINT ACTION_InstallInitialize(MSIPACKAGE *package)
{ {
package->script->CurrentlyScripting = TRUE;
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -6634,52 +6717,35 @@ end:
static UINT ACTION_InstallExecute(MSIPACKAGE *package) static UINT ACTION_InstallExecute(MSIPACKAGE *package)
{ {
int i; UINT rc;
if (!package) if (!package)
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
for (i = 0; i < package->DeferredActionCount; i++) rc = execute_script(package,INSTALL_SCRIPT);
{
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; return rc;
package->DeferredAction = NULL;
return ERROR_SUCCESS;
} }
static UINT ACTION_InstallFinalize(MSIPACKAGE *package) static UINT ACTION_InstallFinalize(MSIPACKAGE *package)
{ {
int i; UINT rc;
if (!package) if (!package)
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
/* turn off scheduleing */
package->script->CurrentlyScripting= FALSE;
/* first do the same as an InstallExecute */ /* first do the same as an InstallExecute */
ACTION_InstallExecute(package); rc = ACTION_InstallExecute(package);
if (rc != ERROR_SUCCESS)
return rc;
/* then handle Commit Actions */ /* then handle Commit Actions */
for (i = 0; i < package->CommitActionCount; i++) rc = execute_script(package,COMMIT_SCRIPT);
{
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; return rc;
package->CommitAction = NULL;
return ERROR_SUCCESS;
} }
static UINT ACTION_ForceReboot(MSIPACKAGE *package) static UINT ACTION_ForceReboot(MSIPACKAGE *package)

View File

@ -179,8 +179,23 @@ typedef struct tagMSIAPPID
BOOL RunAsInteractiveUser; BOOL RunAsInteractiveUser;
} MSIAPPID; } 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); UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action);
void ACTION_FinishCustomActions( MSIPACKAGE* package); void ACTION_FinishCustomActions( MSIPACKAGE* package);
UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action, BOOL execute); 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_feature(MSIPACKAGE* package, LPCWSTR Feature );
int get_loaded_file(MSIPACKAGE* package, LPCWSTR file); int get_loaded_file(MSIPACKAGE* package, LPCWSTR file);
int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path); int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path);
UINT schedule_action(MSIPACKAGE *package, UINT script, LPCWSTR action);
/* control event stuff */ /* control event stuff */
VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event, 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) if (type & 0x100)
{ {
FIXME("Rollback only action... rollbacks not supported yet\n"); FIXME("Rollback only action... rollbacks not supported yet\n");
schedule_action(package, ROLLBACK_SCRIPT, action);
HeapFree(GetProcessHeap(),0,source); HeapFree(GetProcessHeap(),0,source);
HeapFree(GetProcessHeap(),0,target); HeapFree(GetProcessHeap(),0,target);
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
@ -132,37 +133,15 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
} }
if (!execute) if (!execute)
{ {
LPWSTR *newbuf = NULL;
INT count;
if (type & 0x200) if (type & 0x200)
{ {
TRACE("Deferring Commit Action!\n"); TRACE("Deferring Commit Action!\n");
count = package->CommitActionCount; schedule_action(package, COMMIT_SCRIPT, action);
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;
} }
else else
{ {
TRACE("Deferring Action!\n"); TRACE("Deferring Action!\n");
count = package->DeferredActionCount; schedule_action(package, INSTALL_SCRIPT, action);
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;
} }
HeapFree(GetProcessHeap(),0,source); 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, static VOID ControlEvent_DoAction(MSIPACKAGE* package, LPCWSTR argument,
msi_dialog* dialog) msi_dialog* dialog)
{ {
ACTION_PerformAction(package,argument); ACTION_PerformAction(package,argument,TRUE);
} }
static VOID ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument, static VOID ControlEvent_AddLocal(MSIPACKAGE* package, LPCWSTR argument,

View File

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