msi: Reorder functions to avoid forward declarations.
This commit is contained in:
parent
55b89f4a66
commit
796eed1dc7
|
@ -45,14 +45,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||||
|
|
||||||
/*
|
|
||||||
* Prototypes
|
|
||||||
*/
|
|
||||||
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
|
|
||||||
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
|
|
||||||
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI);
|
|
||||||
static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action, UINT* rc, BOOL force);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* consts and values used
|
* consts and values used
|
||||||
*/
|
*/
|
||||||
|
@ -193,15 +185,6 @@ static const WCHAR szValidateProductID[] =
|
||||||
static const WCHAR szWriteEnvironmentStrings[] =
|
static const WCHAR szWriteEnvironmentStrings[] =
|
||||||
{'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t','S','t','r','i','n','g','s',0};
|
{'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t','S','t','r','i','n','g','s',0};
|
||||||
|
|
||||||
/* action handlers */
|
|
||||||
typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
|
|
||||||
|
|
||||||
struct _actions {
|
|
||||||
LPCWSTR action;
|
|
||||||
STANDARDACTIONHANDLER handler;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
* helper functions
|
* helper functions
|
||||||
********************************************************/
|
********************************************************/
|
||||||
|
@ -731,166 +714,6 @@ static UINT msi_set_context(MSIPACKAGE *package)
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************
|
|
||||||
* TOP level entry points
|
|
||||||
*****************************************************/
|
|
||||||
|
|
||||||
UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
|
|
||||||
LPCWSTR szCommandLine )
|
|
||||||
{
|
|
||||||
UINT rc;
|
|
||||||
BOOL ui = FALSE, ui_exists;
|
|
||||||
static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
|
|
||||||
static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
|
|
||||||
|
|
||||||
MSI_SetPropertyW(package, szAction, szInstall);
|
|
||||||
|
|
||||||
package->script = msi_alloc_zero(sizeof(MSISCRIPT));
|
|
||||||
|
|
||||||
package->script->InWhatSequence = SEQUENCE_INSTALL;
|
|
||||||
|
|
||||||
if (szPackagePath)
|
|
||||||
{
|
|
||||||
LPWSTR p, dir;
|
|
||||||
LPCWSTR file;
|
|
||||||
|
|
||||||
dir = strdupW(szPackagePath);
|
|
||||||
p = strrchrW(dir, '\\');
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
*(++p) = 0;
|
|
||||||
file = szPackagePath + (p - dir);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msi_free(dir);
|
|
||||||
dir = msi_alloc(MAX_PATH*sizeof(WCHAR));
|
|
||||||
GetCurrentDirectoryW(MAX_PATH, dir);
|
|
||||||
lstrcatW(dir, szBackSlash);
|
|
||||||
file = szPackagePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
msi_free( package->PackagePath );
|
|
||||||
package->PackagePath = msi_alloc((lstrlenW(dir) + lstrlenW(file) + 1) * sizeof(WCHAR));
|
|
||||||
if (!package->PackagePath)
|
|
||||||
{
|
|
||||||
msi_free(dir);
|
|
||||||
return ERROR_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
lstrcpyW(package->PackagePath, dir);
|
|
||||||
lstrcatW(package->PackagePath, file);
|
|
||||||
msi_free(dir);
|
|
||||||
|
|
||||||
msi_set_sourcedir_props(package, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
msi_parse_command_line( package, szCommandLine, FALSE );
|
|
||||||
|
|
||||||
msi_apply_transforms( package );
|
|
||||||
msi_apply_patches( package );
|
|
||||||
|
|
||||||
if (!szCommandLine && msi_get_property_int( package, szInstalled, 0 ))
|
|
||||||
{
|
|
||||||
TRACE("setting reinstall property\n");
|
|
||||||
MSI_SetPropertyW( package, szReinstall, szAll );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* properties may have been added by a transform */
|
|
||||||
msi_clone_properties( package );
|
|
||||||
msi_set_context( package );
|
|
||||||
|
|
||||||
if ( (msi_get_property_int(package, szUILevel, 0) & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED )
|
|
||||||
{
|
|
||||||
package->script->InWhatSequence |= SEQUENCE_UI;
|
|
||||||
rc = ACTION_ProcessUISequence(package);
|
|
||||||
ui = TRUE;
|
|
||||||
ui_exists = ui_sequence_exists(package);
|
|
||||||
if (rc == ERROR_SUCCESS || !ui_exists)
|
|
||||||
{
|
|
||||||
package->script->InWhatSequence |= SEQUENCE_EXEC;
|
|
||||||
rc = ACTION_ProcessExecSequence(package,ui_exists);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = ACTION_ProcessExecSequence(package,FALSE);
|
|
||||||
|
|
||||||
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_INSTALL_SUSPEND)
|
|
||||||
ACTION_PerformActionSequence(package,-4,ui);
|
|
||||||
else /* failed */
|
|
||||||
ACTION_PerformActionSequence(package,-3,ui);
|
|
||||||
|
|
||||||
/* finish up running custom actions */
|
|
||||||
ACTION_FinishCustomActions(package);
|
|
||||||
|
|
||||||
if (rc == ERROR_SUCCESS && package->need_reboot)
|
|
||||||
return ERROR_SUCCESS_REBOOT_REQUIRED;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI)
|
|
||||||
{
|
|
||||||
UINT rc = ERROR_SUCCESS;
|
|
||||||
MSIRECORD * row = 0;
|
|
||||||
static const WCHAR ExecSeqQuery[] =
|
|
||||||
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
|
||||||
'`','I','n','s','t','a','l','l','E','x','e','c','u','t','e',
|
|
||||||
'S','e','q','u','e','n','c','e','`',' ', 'W','H','E','R','E',' ',
|
|
||||||
'`','S','e','q','u','e','n','c','e','`',' ', '=',' ','%','i',0};
|
|
||||||
|
|
||||||
static const WCHAR UISeqQuery[] =
|
|
||||||
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
|
||||||
'`','I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e',
|
|
||||||
'`', ' ', 'W','H','E','R','E',' ','`','S','e','q','u','e','n','c','e','`',
|
|
||||||
' ', '=',' ','%','i',0};
|
|
||||||
|
|
||||||
if (UI)
|
|
||||||
row = MSI_QueryGetRecord(package->db, UISeqQuery, seq);
|
|
||||||
else
|
|
||||||
row = MSI_QueryGetRecord(package->db, ExecSeqQuery, seq);
|
|
||||||
|
|
||||||
if (row)
|
|
||||||
{
|
|
||||||
LPCWSTR action, cond;
|
|
||||||
|
|
||||||
TRACE("Running the actions\n");
|
|
||||||
|
|
||||||
/* check conditions */
|
|
||||||
cond = MSI_RecordGetString(row,2);
|
|
||||||
|
|
||||||
/* this is a hack to skip errors in the condition code */
|
|
||||||
if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
action = MSI_RecordGetString(row,1);
|
|
||||||
if (!action)
|
|
||||||
{
|
|
||||||
ERR("failed to fetch action\n");
|
|
||||||
rc = ERROR_FUNCTION_FAILED;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UI)
|
|
||||||
rc = ACTION_PerformUIAction(package,action,-1);
|
|
||||||
else
|
|
||||||
rc = ACTION_PerformAction(package,action,-1,FALSE);
|
|
||||||
end:
|
|
||||||
msiobj_release(&row->hdr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MSIPACKAGE* package;
|
MSIPACKAGE* package;
|
||||||
BOOL UI;
|
BOOL UI;
|
||||||
|
@ -1076,60 +899,6 @@ static BOOL ACTION_HandleCustomAction( MSIPACKAGE* package, LPCWSTR action,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* A lot of actions are really important even if they don't do anything
|
|
||||||
* explicit... Lots of properties are set at the beginning of the installation
|
|
||||||
* CostFinalize does a bunch of work to translate the directories and such
|
|
||||||
*
|
|
||||||
* 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 script, BOOL force)
|
|
||||||
{
|
|
||||||
UINT rc = ERROR_SUCCESS;
|
|
||||||
BOOL handled;
|
|
||||||
|
|
||||||
TRACE("Performing action (%s)\n",debugstr_w(action));
|
|
||||||
|
|
||||||
handled = ACTION_HandleStandardAction(package, action, &rc, force);
|
|
||||||
|
|
||||||
if (!handled)
|
|
||||||
handled = ACTION_HandleCustomAction(package, action, &rc, script, force);
|
|
||||||
|
|
||||||
if (!handled)
|
|
||||||
{
|
|
||||||
WARN("unhandled msi action %s\n",debugstr_w(action));
|
|
||||||
rc = ERROR_FUNCTION_NOT_CALLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT script)
|
|
||||||
{
|
|
||||||
UINT rc = ERROR_SUCCESS;
|
|
||||||
BOOL handled = FALSE;
|
|
||||||
|
|
||||||
TRACE("Performing action (%s)\n",debugstr_w(action));
|
|
||||||
|
|
||||||
handled = ACTION_HandleStandardAction(package, action, &rc,TRUE);
|
|
||||||
|
|
||||||
if (!handled)
|
|
||||||
handled = ACTION_HandleCustomAction(package, action, &rc, script, FALSE);
|
|
||||||
|
|
||||||
if( !handled && ACTION_DialogBox(package,action) == ERROR_SUCCESS )
|
|
||||||
handled = TRUE;
|
|
||||||
|
|
||||||
if (!handled)
|
|
||||||
{
|
|
||||||
WARN("unhandled msi action %s\n",debugstr_w(action));
|
|
||||||
rc = ERROR_FUNCTION_NOT_CALLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actual Action Handlers
|
* Actual Action Handlers
|
||||||
*/
|
*/
|
||||||
|
@ -6391,7 +6160,15 @@ static UINT ACTION_UnregisterTypeLibraries( MSIPACKAGE *package )
|
||||||
return msi_unimplemented_action_stub( package, "UnregisterTypeLibraries", table );
|
return msi_unimplemented_action_stub( package, "UnregisterTypeLibraries", table );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct _actions StandardActions[] = {
|
typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
const WCHAR *action;
|
||||||
|
UINT (*handler)(MSIPACKAGE *);
|
||||||
|
}
|
||||||
|
StandardActions[] =
|
||||||
|
{
|
||||||
{ szAllocateRegistrySpace, ACTION_AllocateRegistrySpace },
|
{ szAllocateRegistrySpace, ACTION_AllocateRegistrySpace },
|
||||||
{ szAppSearch, ACTION_AppSearch },
|
{ szAppSearch, ACTION_AppSearch },
|
||||||
{ szBindImage, ACTION_BindImage },
|
{ szBindImage, ACTION_BindImage },
|
||||||
|
@ -6519,3 +6296,208 @@ static BOOL ACTION_HandleStandardAction(MSIPACKAGE *package, LPCWSTR action,
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action, UINT script, BOOL force)
|
||||||
|
{
|
||||||
|
UINT rc = ERROR_SUCCESS;
|
||||||
|
BOOL handled;
|
||||||
|
|
||||||
|
TRACE("Performing action (%s)\n", debugstr_w(action));
|
||||||
|
|
||||||
|
handled = ACTION_HandleStandardAction(package, action, &rc, force);
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
handled = ACTION_HandleCustomAction(package, action, &rc, script, force);
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
{
|
||||||
|
WARN("unhandled msi action %s\n", debugstr_w(action));
|
||||||
|
rc = ERROR_FUNCTION_NOT_CALLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT ACTION_PerformUIAction(MSIPACKAGE *package, const WCHAR *action, UINT script)
|
||||||
|
{
|
||||||
|
UINT rc = ERROR_SUCCESS;
|
||||||
|
BOOL handled = FALSE;
|
||||||
|
|
||||||
|
TRACE("Performing action (%s)\n", debugstr_w(action));
|
||||||
|
|
||||||
|
handled = ACTION_HandleStandardAction(package, action, &rc,TRUE);
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
handled = ACTION_HandleCustomAction(package, action, &rc, script, FALSE);
|
||||||
|
|
||||||
|
if( !handled && ACTION_DialogBox(package, action) == ERROR_SUCCESS )
|
||||||
|
handled = TRUE;
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
{
|
||||||
|
WARN("unhandled msi action %s\n", debugstr_w(action));
|
||||||
|
rc = ERROR_FUNCTION_NOT_CALLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq, BOOL UI)
|
||||||
|
{
|
||||||
|
UINT rc = ERROR_SUCCESS;
|
||||||
|
MSIRECORD *row = 0;
|
||||||
|
|
||||||
|
static const WCHAR ExecSeqQuery[] =
|
||||||
|
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'`','I','n','s','t','a','l','l','E','x','e','c','u','t','e',
|
||||||
|
'S','e','q','u','e','n','c','e','`',' ', 'W','H','E','R','E',' ',
|
||||||
|
'`','S','e','q','u','e','n','c','e','`',' ', '=',' ','%','i',0};
|
||||||
|
static const WCHAR UISeqQuery[] =
|
||||||
|
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'`','I','n','s','t','a','l','l','U','I','S','e','q','u','e','n','c','e',
|
||||||
|
'`', ' ', 'W','H','E','R','E',' ','`','S','e','q','u','e','n','c','e','`',
|
||||||
|
' ', '=',' ','%','i',0};
|
||||||
|
|
||||||
|
if (UI)
|
||||||
|
row = MSI_QueryGetRecord(package->db, UISeqQuery, seq);
|
||||||
|
else
|
||||||
|
row = MSI_QueryGetRecord(package->db, ExecSeqQuery, seq);
|
||||||
|
|
||||||
|
if (row)
|
||||||
|
{
|
||||||
|
LPCWSTR action, cond;
|
||||||
|
|
||||||
|
TRACE("Running the actions\n");
|
||||||
|
|
||||||
|
/* check conditions */
|
||||||
|
cond = MSI_RecordGetString(row, 2);
|
||||||
|
|
||||||
|
/* this is a hack to skip errors in the condition code */
|
||||||
|
if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
action = MSI_RecordGetString(row, 1);
|
||||||
|
if (!action)
|
||||||
|
{
|
||||||
|
ERR("failed to fetch action\n");
|
||||||
|
rc = ERROR_FUNCTION_FAILED;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UI)
|
||||||
|
rc = ACTION_PerformUIAction(package, action, -1);
|
||||||
|
else
|
||||||
|
rc = ACTION_PerformAction(package, action, -1, FALSE);
|
||||||
|
end:
|
||||||
|
msiobj_release(&row->hdr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************
|
||||||
|
* TOP level entry points
|
||||||
|
*****************************************************/
|
||||||
|
|
||||||
|
UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath,
|
||||||
|
LPCWSTR szCommandLine )
|
||||||
|
{
|
||||||
|
UINT rc;
|
||||||
|
BOOL ui = FALSE, ui_exists;
|
||||||
|
|
||||||
|
static const WCHAR szAction[] = {'A','C','T','I','O','N',0};
|
||||||
|
static const WCHAR szInstall[] = {'I','N','S','T','A','L','L',0};
|
||||||
|
|
||||||
|
MSI_SetPropertyW(package, szAction, szInstall);
|
||||||
|
|
||||||
|
package->script = msi_alloc_zero(sizeof(MSISCRIPT));
|
||||||
|
package->script->InWhatSequence = SEQUENCE_INSTALL;
|
||||||
|
|
||||||
|
if (szPackagePath)
|
||||||
|
{
|
||||||
|
LPWSTR p, dir;
|
||||||
|
LPCWSTR file;
|
||||||
|
|
||||||
|
dir = strdupW(szPackagePath);
|
||||||
|
p = strrchrW(dir, '\\');
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
*(++p) = 0;
|
||||||
|
file = szPackagePath + (p - dir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msi_free(dir);
|
||||||
|
dir = msi_alloc(MAX_PATH * sizeof(WCHAR));
|
||||||
|
GetCurrentDirectoryW(MAX_PATH, dir);
|
||||||
|
lstrcatW(dir, szBackSlash);
|
||||||
|
file = szPackagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
msi_free( package->PackagePath );
|
||||||
|
package->PackagePath = msi_alloc((lstrlenW(dir) + lstrlenW(file) + 1) * sizeof(WCHAR));
|
||||||
|
if (!package->PackagePath)
|
||||||
|
{
|
||||||
|
msi_free(dir);
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstrcpyW(package->PackagePath, dir);
|
||||||
|
lstrcatW(package->PackagePath, file);
|
||||||
|
msi_free(dir);
|
||||||
|
|
||||||
|
msi_set_sourcedir_props(package, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
msi_parse_command_line( package, szCommandLine, FALSE );
|
||||||
|
|
||||||
|
msi_apply_transforms( package );
|
||||||
|
msi_apply_patches( package );
|
||||||
|
|
||||||
|
if (!szCommandLine && msi_get_property_int( package, szInstalled, 0 ))
|
||||||
|
{
|
||||||
|
TRACE("setting reinstall property\n");
|
||||||
|
MSI_SetPropertyW( package, szReinstall, szAll );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* properties may have been added by a transform */
|
||||||
|
msi_clone_properties( package );
|
||||||
|
msi_set_context( package );
|
||||||
|
|
||||||
|
if ( (msi_get_property_int(package, szUILevel, 0) & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED )
|
||||||
|
{
|
||||||
|
package->script->InWhatSequence |= SEQUENCE_UI;
|
||||||
|
rc = ACTION_ProcessUISequence(package);
|
||||||
|
ui = TRUE;
|
||||||
|
ui_exists = ui_sequence_exists(package);
|
||||||
|
if (rc == ERROR_SUCCESS || !ui_exists)
|
||||||
|
{
|
||||||
|
package->script->InWhatSequence |= SEQUENCE_EXEC;
|
||||||
|
rc = ACTION_ProcessExecSequence(package, ui_exists);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = ACTION_ProcessExecSequence(package, FALSE);
|
||||||
|
|
||||||
|
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_INSTALL_SUSPEND)
|
||||||
|
ACTION_PerformActionSequence(package, -4, ui);
|
||||||
|
else /* failed */
|
||||||
|
ACTION_PerformActionSequence(package, -3, ui);
|
||||||
|
|
||||||
|
/* finish up running custom actions */
|
||||||
|
ACTION_FinishCustomActions(package);
|
||||||
|
|
||||||
|
if (rc == ERROR_SUCCESS && package->need_reboot)
|
||||||
|
return ERROR_SUCCESS_REBOOT_REQUIRED;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue