Keep track of what sequence we are in and register unique

actions. This allows us to make sure actions and custom actions
flagged to run only once, actually run only once.
Also clean up some of the numeric constants in custom.c using the
defined values from msidefs.h.
This commit is contained in:
Aric Stewart 2005-06-30 20:45:43 +00:00 committed by Alexandre Julliard
parent 8ee142a179
commit c9802931c1
5 changed files with 123 additions and 11 deletions

View File

@ -447,6 +447,8 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT));
memset(package->script,0,sizeof(MSISCRIPT));
package->script->InWhatSequence = SEQUENCE_INSTALL;
package->msiFilePath= strdupW(msiFilePath);
if (szPackagePath)
@ -540,10 +542,14 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
{
if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED)
{
package->script->InWhatSequence |= SEQUENCE_UI;
rc = ACTION_ProcessUISequence(package);
ui = TRUE;
if (rc == ERROR_SUCCESS)
{
package->script->InWhatSequence |= SEQUENCE_EXEC;
rc = ACTION_ProcessExecSequence(package,TRUE);
}
}
else
rc = ACTION_ProcessExecSequence(package,FALSE);
@ -3847,6 +3853,7 @@ static UINT ACTION_ExecuteAction(MSIPACKAGE *package)
level = load_dynamic_property(package,szUILevel,NULL);
MSI_SetPropertyW(package,szUILevel,szTwo);
package->script->InWhatSequence |= SEQUENCE_EXEC;
rc = ACTION_ProcessExecSequence(package,FALSE);
MSI_SetPropertyW(package,szUILevel,level);
HeapFree(GetProcessHeap(),0,level);

View File

@ -187,13 +187,19 @@ enum SCRIPTS {
TOTAL_SCRIPTS = 3
};
#define SEQUENCE_UI 0x1
#define SEQUENCE_EXEC 0x2
#define SEQUENCE_INSTALL 0x10
typedef struct tagMSISCRIPT
{
LPWSTR *Actions[TOTAL_SCRIPTS];
UINT ActionCount[TOTAL_SCRIPTS];
BOOL ExecuteSequenceRun;
BOOL FindRelatedProductsRun;
BOOL CurrentlyScripting;
UINT InWhatSequence;
LPWSTR *UniqueActions;
UINT UniqueActionsCount;
}MSISCRIPT;
@ -234,6 +240,8 @@ void reduce_to_longfilename(WCHAR*);
void reduce_to_shortfilename(WCHAR*);
LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR);
void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature);
UINT register_unique_action(MSIPACKAGE *, LPCWSTR);
BOOL check_unique_action(MSIPACKAGE *, LPCWSTR);
WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );

View File

@ -36,6 +36,7 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/summa
#include "wine/debug.h"
#include "fdi.h"
#include "msi.h"
#include "msidefs.h"
#include "msiquery.h"
#include "msvcrt/fcntl.h"
#include "objbase.h"
@ -74,6 +75,45 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source,
static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
LPCWSTR target, const INT type, LPCWSTR action);
static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options)
{
if (!package->script)
return TRUE;
if ((options & msidbCustomActionTypeClientRepeat) ==
msidbCustomActionTypeClientRepeat)
{
if (!(package->script->InWhatSequence & SEQUENCE_UI &&
package->script->InWhatSequence & SEQUENCE_EXEC))
{
TRACE("Skipping action due to dbCustomActionTypeClientRepeat option.\n");
return FALSE;
}
}
else if (options & msidbCustomActionTypeFirstSequence)
{
if (package->script->InWhatSequence & SEQUENCE_UI &&
package->script->InWhatSequence & SEQUENCE_EXEC )
{
TRACE("Skipping action due to msidbCustomActionTypeFirstSequence option.\n");
return FALSE;
}
}
else if (options & msidbCustomActionTypeOncePerProcess)
{
if (check_unique_action(package,action))
{
TRACE("Skipping action due to msidbCustomActionTypeOncePerProcess option.\n");
return FALSE;
}
else
register_unique_action(package,action);
}
return TRUE;
}
UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
{
UINT rc = ERROR_SUCCESS;
@ -101,9 +141,15 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
debugstr_w(source), debugstr_w(target));
/* handle some of the deferred actions */
if (type & 0x400)
if (type & msidbCustomActionTypeTSAware)
FIXME("msidbCustomActionTypeTSAware not handled\n");
if (type & msidbCustomActionTypeInScript)
{
if (type & 0x100)
if (type & msidbCustomActionTypeNoImpersonate)
FIXME("msidbCustomActionTypeNoImpersonate not handled\n");
if (type & msidbCustomActionTypeRollback)
{
FIXME("Rollback only action... rollbacks not supported yet\n");
schedule_action(package, ROLLBACK_SCRIPT, action);
@ -114,7 +160,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
}
if (!execute)
{
if (type & 0x200)
if (type & msidbCustomActionTypeCommit)
{
TRACE("Deferring Commit Action!\n");
schedule_action(package, COMMIT_SCRIPT, action);
@ -136,11 +182,16 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute)
static const WCHAR szActionData[] = {
'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0};
static const WCHAR szBlank[] = {' ',0};
LPWSTR actiondata = load_dynamic_property(package,action,NULL);
if (actiondata)
MSI_SetPropertyW(package,szActionData,actiondata);
else
MSI_SetPropertyW(package,szActionData,szBlank);
}
}
else if (!check_execution_scheduling_options(package,action,type))
return ERROR_SUCCESS;
switch (type & CUSTOM_ACTION_TYPE_MASK)
{
@ -304,7 +355,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type,
{
UINT rc = ERROR_SUCCESS;
if (!(type & 0x80))
if (!(type & msidbCustomActionTypeAsync))
{
/* synchronous */
TRACE("Synchronous Execution of action %s\n",debugstr_w(Name));
@ -313,7 +364,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type,
else
msi_dialog_check_messages(ThreadHandle);
if (!(type & 0x40))
if (!(type & msidbCustomActionTypeContinue))
{
if (ProcessHandle)
rc = process_action_return_value(2,ProcessHandle);
@ -331,7 +382,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type,
{
TRACE("Asynchronous Execution of action %s\n",debugstr_w(Name));
/* asynchronous */
if (type & 0x40)
if (type & msidbCustomActionTypeContinue)
{
if (ProcessHandle)
{

View File

@ -576,6 +576,11 @@ void ACTION_free_package_structures( MSIPACKAGE* package)
HeapFree(GetProcessHeap(),0,package->script->Actions[i]);
}
for (i = 0; i < package->script->UniqueActionsCount; i++)
HeapFree(GetProcessHeap(),0,package->script->UniqueActions[i]);
HeapFree(GetProcessHeap(),0,package->script->UniqueActions);
HeapFree(GetProcessHeap(),0,package->script);
}
@ -913,6 +918,45 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature)
}
}
UINT register_unique_action(MSIPACKAGE *package, LPCWSTR action)
{
UINT count;
LPWSTR *newbuf = NULL;
if (!package || !package->script)
return FALSE;
TRACE("Registering Action %s as having fun\n",debugstr_w(action));
count = package->script->UniqueActionsCount;
package->script->UniqueActionsCount++;
if (count != 0)
newbuf = HeapReAlloc(GetProcessHeap(),0,
package->script->UniqueActions,
package->script->UniqueActionsCount* sizeof(LPWSTR));
else
newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR));
newbuf[count] = strdupW(action);
package->script->UniqueActions = newbuf;
return ERROR_SUCCESS;
}
BOOL check_unique_action(MSIPACKAGE *package, LPCWSTR action)
{
INT i;
if (!package || !package->script)
return FALSE;
for (i = 0; i < package->script->UniqueActionsCount; i++)
if (!strcmpW(package->script->UniqueActions[i],action))
return TRUE;
return FALSE;
}
WCHAR* generate_error_string(MSIPACKAGE *package, UINT error, DWORD count, ... )
{
static const WCHAR query[] = {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ','F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ','`','E','r','r','o','r','`',' ','=',' ','%','i',0};

View File

@ -211,12 +211,14 @@ UINT ACTION_FindRelatedProducts(MSIPACKAGE *package)
UINT rc = ERROR_SUCCESS;
MSIQUERY *view;
if (package->script && package->script->FindRelatedProductsRun)
if (check_unique_action(package,szFindRelatedProducts))
{
TRACE("Skipping FindRelatedProducts action: already done on client side\n");
return ERROR_SUCCESS;
}
else
register_unique_action(package,szFindRelatedProducts);
if (package->script)
package->script->FindRelatedProductsRun = TRUE;
rc = MSI_DatabaseOpenViewW(package->db, Query, &view);
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;