diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 81681bb8753..f29deff5d96 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -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); - - 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 @@ 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,29 +1422,49 @@ 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); - 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 @@ 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) diff --git a/dlls/msi/action.h b/dlls/msi/action.h index 0f8c4a688c5..7a49854c5c4 100644 --- a/dlls/msi/action.h +++ b/dlls/msi/action.h @@ -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, diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c index 8c454443304..7ee72e520c6 100644 --- a/dlls/msi/custom.c +++ b/dlls/msi/custom.c @@ -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); diff --git a/dlls/msi/events.c b/dlls/msi/events.c index e65f64840ac..0fa27291e7a 100644 --- a/dlls/msi/events.c +++ b/dlls/msi/events.c @@ -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, diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 5ba99abf6d2..560415c59d3 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -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; @@ -224,8 +220,7 @@ typedef struct tagMSIPACKAGE UINT CurrentInstallState; msi_dialog *dialog; LPWSTR next_dialog; - - BOOL ExecuteSequenceRun; + struct _subscriptions *EventSubscriptions; } MSIPACKAGE;